diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-05 16:36:30 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-05 16:36:30 -0700 |
commit | f4d33337eac4007793ca11fd1ab68d91ce7aa762 (patch) | |
tree | b775ad213179822225a3e1c1a27e4cc16f8aff68 /drivers/staging | |
parent | 91c2ff7708d4edf73ef1f0abb3ea4a44b4b0cf1d (diff) | |
parent | 0f3bf3dc1ca394a8385079a5653088672b65c5c4 (diff) | |
download | blackbird-op-linux-f4d33337eac4007793ca11fd1ab68d91ce7aa762.tar.gz blackbird-op-linux-f4d33337eac4007793ca11fd1ab68d91ce7aa762.zip |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- removal of sn9c102. This device driver was replaced a long time ago
by gspca
- solo6x10 and go7007 webcam drivers moved from staging into
mainstream. They were waiting for an API to allow setting the image
detection matrix
- SDR drivers moved from staging into mainstream: sdr-msi3101 (renamed
as msi2500) and rtl2832
- added SDR driver for airspy
- added demux driver: si2165
- rework at several RC subsystem, making the code for RC-5 SZ variant
to be added at the standard RC5 decoder
- added decoder for the XMP IR protocol
- tuner driver moved from staging into mainstream: msi3101 (renamed as
msi001)
- added documentation for some additional SDR pixfmt
- some device tree bindings documented
- added support for exynos3250 at s5p-jpeg
- remove the obsolete, unmaintained and broken mx1_camera driver
- added support for remote controllers at au0828 driver
- added a RC driver: sunxi-cir
- several driver fixes, enhancements and cleanups.
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (455 commits)
[media] cx23885: fix UNSET/TUNER_ABSENT confusion
[media] coda: fix build error by making reset control optional
[media] radio-miropcm20: fix sparse NULL pointer warning
[media] MAINTAINERS: Update go7007 pattern
[media] MAINTAINERS: Update solo6x10 patterns
[media] media: atmel-isi: add primary DT support
[media] media: atmel-isi: convert the pdata from pointer to structure
[media] media: atmel-isi: add v4l2 async probe support
[media] rcar_vin: add devicetree support
[media] media: pxa_camera device-tree support
[media] media: mt9m111: add device-tree suppport
[media] soc_camera: add support for dt binding soc_camera drivers
[media] media: soc_camera: pxa_camera documentation device-tree support
[media] media: mt9m111: add device-tree documentation
[media] s5p-mfc: remove unnecessary calling to function video_devdata()
[media] s5p-jpeg: add chroma subsampling adjustment for Exynos3250
[media] s5p-jpeg: Prevent erroneous downscaling for Exynos3250 SoC
[media] s5p-jpeg: Assure proper crop rectangle initialization
[media] s5p-jpeg: fix g_selection op
[media] s5p-jpeg: Adjust jpeg_bound_align_image to Exynos3250 needs
...
Diffstat (limited to 'drivers/staging')
78 files changed, 67 insertions, 27411 deletions
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index a9f2e63a7c9c..3323eb5e77b0 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -29,20 +29,10 @@ source "drivers/staging/media/davinci_vpfe/Kconfig" source "drivers/staging/media/dt3155v4l/Kconfig" -source "drivers/staging/media/go7007/Kconfig" - -source "drivers/staging/media/msi3101/Kconfig" - source "drivers/staging/media/omap24xx/Kconfig" -source "drivers/staging/media/sn9c102/Kconfig" - -source "drivers/staging/media/solo6x10/Kconfig" - source "drivers/staging/media/omap4iss/Kconfig" -source "drivers/staging/media/rtl2832u_sdr/Kconfig" - # Keep LIRC at the end, as it has sub-menus source "drivers/staging/media/lirc/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index 8e2c5d272162..7db83f373f63 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -2,14 +2,9 @@ obj-$(CONFIG_DVB_AS102) += as102/ obj-$(CONFIG_I2C_BCM2048) += bcm2048/ obj-$(CONFIG_DVB_CXD2099) += cxd2099/ obj-$(CONFIG_LIRC_STAGING) += lirc/ -obj-$(CONFIG_SOLO6X10) += solo6x10/ obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/ -obj-$(CONFIG_VIDEO_GO7007) += go7007/ -obj-$(CONFIG_USB_MSI3101) += msi3101/ obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ -obj-$(CONFIG_USB_SN9C102) += sn9c102/ obj-$(CONFIG_VIDEO_OMAP2) += omap24xx/ obj-$(CONFIG_VIDEO_TCM825X) += omap24xx/ -obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832u_sdr/ diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index bbf236e842a9..2bba370a47ca 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -369,13 +369,12 @@ static int bcm2048_send_command(struct bcm2048_device *bdev, unsigned int reg, data[0] = reg & 0xff; data[1] = value & 0xff; - if (i2c_master_send(client, data, 2) == 2) { + if (i2c_master_send(client, data, 2) == 2) return 0; - } else { - dev_err(&bdev->client->dev, "BCM I2C error!\n"); - dev_err(&bdev->client->dev, "Is Bluetooth up and running?\n"); - return -EIO; - } + + dev_err(&bdev->client->dev, "BCM I2C error!\n"); + dev_err(&bdev->client->dev, "Is Bluetooth up and running?\n"); + return -EIO; } static int bcm2048_recv_command(struct bcm2048_device *bdev, unsigned int reg, @@ -725,8 +724,8 @@ static int bcm2048_get_fm_deemphasis(struct bcm2048_device *bdev) if (!err) { if (value & BCM2048_DE_EMPHASIS_SELECT) return BCM2048_DE_EMPHASIS_75us; - else - return BCM2048_DE_EMPHASIS_50us; + + return BCM2048_DE_EMPHASIS_50us; } return err; @@ -1971,7 +1970,8 @@ static ssize_t bcm2048_##prop##_write(struct device *dev, \ if (!bdev) \ return -ENODEV; \ \ - sscanf(buf, mask, &value); \ + if (sscanf(buf, mask, &value) != 1) \ + return -EINVAL; \ \ if (check) \ return -EDOM; \ @@ -2242,6 +2242,7 @@ static ssize_t bcm2048_fops_read(struct file *file, char __user *buf, i = 0; while (i < count) { unsigned char tmpbuf[3]; + tmpbuf[i] = bdev->rds_info.radio_text[bdev->rd_index+i+2]; tmpbuf[i+1] = bdev->rds_info.radio_text[bdev->rd_index+i+1]; tmpbuf[i+2] = ((bdev->rds_info.radio_text[bdev->rd_index+i] @@ -2598,7 +2599,6 @@ static int bcm2048_i2c_driver_probe(struct i2c_client *client, bdev = kzalloc(sizeof(*bdev), GFP_KERNEL); if (!bdev) { - dev_dbg(&client->dev, "Failed to alloc video device.\n"); err = -ENOMEM; goto exit; } @@ -2618,7 +2618,7 @@ static int bcm2048_i2c_driver_probe(struct i2c_client *client, if (client->irq) { err = request_irq(client->irq, - bcm2048_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, + bcm2048_handler, IRQF_TRIGGER_FALLING, client->name, bdev); if (err < 0) { dev_err(&client->dev, "Could not request IRQ\n"); diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c index b7044a380fe3..bdc7f005b3ba 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c @@ -1268,6 +1268,7 @@ static int ipipe_s_config(struct v4l2_subdev *sd, struct vpfe_ipipe_config *cfg) for (i = 0; i < ARRAY_SIZE(ipipe_modules); i++) { unsigned int bit = 1 << i; + if (cfg->flag & bit) { const struct ipipe_module_if *module_if = &ipipe_modules[i]; @@ -1310,6 +1311,7 @@ static int ipipe_g_config(struct v4l2_subdev *sd, struct vpfe_ipipe_config *cfg) for (i = 1; i < ARRAY_SIZE(ipipe_modules); i++) { unsigned int bit = 1 << i; + if (cfg->flag & bit) { const struct ipipe_module_if *module_if = &ipipe_modules[i]; diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h b/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h index 010fdb247faf..81176fb9d164 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h @@ -479,7 +479,6 @@ #define RSZ_TYP_Y_SHIFT 0 #define RSZ_TYP_C_SHIFT 1 #define RSZ_LPF_INT_MASK 0x3f -#define RSZ_LPF_INT_MASK 0x3f #define RSZ_LPF_INT_C_SHIFT 6 #define RSZ_H_PHS_MASK 0x3fff #define RSZ_H_DIF_MASK 0x3fff diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c index 59540cd4bb98..6d4893b44c1f 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c @@ -196,6 +196,7 @@ static int ipipeif_hw_setup(struct v4l2_subdev *sd) int data_shift; int pack_mode; int source1; + int tmp; ipipeif_base_addr = ipipeif->ipipeif_base_addr; @@ -206,8 +207,8 @@ static int ipipeif_hw_setup(struct v4l2_subdev *sd) outformat = &ipipeif->formats[IPIPEIF_PAD_SOURCE]; /* Combine all the fields to make CFG1 register of IPIPEIF */ - val = get_oneshot_mode(ipipeif->input); - if (val < 0) { + tmp = val = get_oneshot_mode(ipipeif->input); + if (tmp < 0) { pr_err("ipipeif: links setup required"); return -EINVAL; } diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c index 8e13bd494c98..8828d6c2aab1 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c @@ -219,7 +219,7 @@ configure_resizer_out_params(struct vpfe_resizer_device *resizer, int index, * @resizer: Pointer to VPFE resizer subdevice. * @index: index RSZ_A-resizer-A RSZ_B-resizer-B. */ -void +static void resizer_calculate_resize_ratios(struct vpfe_resizer_device *resizer, int index) { struct resizer_params *param = &resizer->config; @@ -310,7 +310,7 @@ resizer_calculate_sdram_offsets(struct vpfe_resizer_device *resizer, int index) return 0; } -int resizer_configure_output_win(struct vpfe_resizer_device *resizer) +static int resizer_configure_output_win(struct vpfe_resizer_device *resizer) { struct resizer_params *param = &resizer->config; struct vpfe_rsz_output_spec output_specs; diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index d95c427043d4..6f9171c39bdc 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -1606,7 +1606,6 @@ int vpfe_video_init(struct vpfe_video_device *video, const char *name) if (ret < 0) return ret; - set_bit(V4L2_FL_USE_FH_PRIO, &video->video_dev.flags); video_set_drvdata(&video->video_dev, video); return 0; diff --git a/drivers/staging/media/go7007/Kconfig b/drivers/staging/media/go7007/Kconfig deleted file mode 100644 index 95a3af644a92..000000000000 --- a/drivers/staging/media/go7007/Kconfig +++ /dev/null @@ -1,51 +0,0 @@ -config VIDEO_GO7007 - tristate "WIS GO7007 MPEG encoder support" - depends on VIDEO_DEV && I2C - depends on SND && USB - select VIDEOBUF2_VMALLOC - select VIDEO_TUNER - select CYPRESS_FIRMWARE - select SND_PCM - select VIDEO_SONY_BTF_MPX if MEDIA_SUBDRV_AUTOSELECT - select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT - select VIDEO_TW2804 if MEDIA_SUBDRV_AUTOSELECT - select VIDEO_TW9903 if MEDIA_SUBDRV_AUTOSELECT - select VIDEO_TW9906 if MEDIA_SUBDRV_AUTOSELECT - select VIDEO_OV7640 if MEDIA_SUBDRV_AUTOSELECT - select VIDEO_UDA1342 if MEDIA_SUBDRV_AUTOSELECT - ---help--- - This is a video4linux driver for the WIS GO7007 MPEG - encoder chip. - - To compile this driver as a module, choose M here: the - module will be called go7007. - -config VIDEO_GO7007_USB - tristate "WIS GO7007 USB support" - depends on VIDEO_GO7007 && USB - ---help--- - This is a video4linux driver for the WIS GO7007 MPEG - encoder chip over USB. - - To compile this driver as a module, choose M here: the - module will be called go7007-usb. - -config VIDEO_GO7007_LOADER - tristate "WIS GO7007 Loader support" - depends on VIDEO_GO7007 - default y - ---help--- - This is a go7007 firmware loader driver for the WIS GO7007 - MPEG encoder chip over USB. - - To compile this driver as a module, choose M here: the - module will be called go7007-loader. - -config VIDEO_GO7007_USB_S2250_BOARD - tristate "Sensoray 2250/2251 support" - depends on VIDEO_GO7007_USB && USB - ---help--- - This is a video4linux driver for the Sensoray 2250/2251 device. - - To compile this driver as a module, choose M here: the - module will be called s2250. diff --git a/drivers/staging/media/go7007/Makefile b/drivers/staging/media/go7007/Makefile deleted file mode 100644 index 9c6ad4a263ec..000000000000 --- a/drivers/staging/media/go7007/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -obj-$(CONFIG_VIDEO_GO7007) += go7007.o -obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o -obj-$(CONFIG_VIDEO_GO7007_LOADER) += go7007-loader.o -obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o - -go7007-y := go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \ - snd-go7007.o - -s2250-y := s2250-board.o - -# Uncomment when the saa7134 patches get into upstream -#obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o -#ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/pci/saa7134 - -ccflags-$(CONFIG_VIDEO_GO7007_LOADER:m=y) += -Idrivers/media/common diff --git a/drivers/staging/media/go7007/README b/drivers/staging/media/go7007/README deleted file mode 100644 index 3af0d9062811..000000000000 --- a/drivers/staging/media/go7007/README +++ /dev/null @@ -1,137 +0,0 @@ -Todo: - - create an API for motion detection - - let s2250-board use i2c subdevs as well instead of hardcoding - support for the i2c devices. - - when the driver is moved out of staging, support for saa7134-go7007 - should be added to the saa7134 driver. The patch for that is - included below. - -Patch for saa7134: - -diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c -index dc68cf1..9a53794 100644 ---- a/drivers/media/pci/saa7134/saa7134-cards.c -+++ b/drivers/media/pci/saa7134/saa7134-cards.c -@@ -5790,6 +5790,29 @@ struct saa7134_board saa7134_boards[] = { - .gpio = 0x6010000, - } }, - }, -+ [SAA7134_BOARD_WIS_VOYAGER] = { -+ .name = "WIS Voyager or compatible", -+ .audio_clock = 0x00200000, -+ .tuner_type = TUNER_PHILIPS_TDA8290, -+ .radio_type = UNSET, -+ .tuner_addr = ADDR_UNSET, -+ .radio_addr = ADDR_UNSET, -+ .mpeg = SAA7134_MPEG_GO7007, -+ .inputs = { { -+ .name = name_comp1, -+ .vmux = 0, -+ .amux = LINE2, -+ }, { -+ .name = name_tv, -+ .vmux = 3, -+ .amux = TV, -+ .tv = 1, -+ }, { -+ .name = name_svideo, -+ .vmux = 6, -+ .amux = LINE1, -+ } }, -+ }, - - }; - -@@ -7037,6 +7060,12 @@ struct pci_device_id saa7134_pci_tbl[] = { - .subdevice = 0x0911, - .driver_data = SAA7134_BOARD_SENSORAY811_911, - }, { -+ .vendor = PCI_VENDOR_ID_PHILIPS, -+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133, -+ .subvendor = 0x1905, /* WIS */ -+ .subdevice = 0x7007, -+ .driver_data = SAA7134_BOARD_WIS_VOYAGER, -+ }, { - /* --- boards without eeprom + subsystem ID --- */ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, -diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c -index 8fd24e7..0a849ea 100644 ---- a/drivers/media/pci/saa7134/saa7134-core.c -+++ b/drivers/media/pci/saa7134/saa7134-core.c -@@ -156,6 +156,8 @@ static void request_module_async(struct work_struct *work){ - request_module("saa7134-empress"); - if (card_is_dvb(dev)) - request_module("saa7134-dvb"); -+ if (card_is_go7007(dev)) -+ request_module("saa7134-go7007"); - if (alsa) { - if (dev->pci->device != PCI_DEVICE_ID_PHILIPS_SAA7130) - request_module("saa7134-alsa"); -@@ -557,8 +559,12 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id) - saa7134_irq_vbi_done(dev,status); - - if ((report & SAA7134_IRQ_REPORT_DONE_RA2) && -- card_has_mpeg(dev)) -- saa7134_irq_ts_done(dev,status); -+ card_has_mpeg(dev)) { -+ if (dev->mops->irq_ts_done != NULL) -+ dev->mops->irq_ts_done(dev, status); -+ else -+ saa7134_irq_ts_done(dev, status); -+ } - - if (report & SAA7134_IRQ_REPORT_GPIO16) { - switch (dev->has_remote) { -diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h -index 62169dd..5fad39a 100644 ---- a/drivers/media/pci/saa7134/saa7134.h -+++ b/drivers/media/pci/saa7134/saa7134.h -@@ -334,6 +334,7 @@ struct saa7134_card_ir { - #define SAA7134_BOARD_KWORLD_PC150U 189 - #define SAA7134_BOARD_ASUSTeK_PS3_100 190 - #define SAA7134_BOARD_HAWELL_HW_9004V1 191 -+#define SAA7134_BOARD_WIS_VOYAGER 192 - - #define SAA7134_MAXBOARDS 32 - #define SAA7134_INPUT_MAX 8 -@@ -364,6 +365,7 @@ enum saa7134_mpeg_type { - SAA7134_MPEG_UNUSED, - SAA7134_MPEG_EMPRESS, - SAA7134_MPEG_DVB, -+ SAA7134_MPEG_GO7007, - }; - - enum saa7134_mpeg_ts_type { -@@ -403,6 +405,7 @@ struct saa7134_board { - #define card_has_radio(dev) (NULL != saa7134_boards[dev->board].radio.name) - #define card_is_empress(dev) (SAA7134_MPEG_EMPRESS == saa7134_boards[dev->board].mpeg) - #define card_is_dvb(dev) (SAA7134_MPEG_DVB == saa7134_boards[dev->board].mpeg) -+#define card_is_go7007(dev) (SAA7134_MPEG_GO7007 == saa7134_boards[dev->board].mpeg) - #define card_has_mpeg(dev) (SAA7134_MPEG_UNUSED != saa7134_boards[dev->board].mpeg) - #define card(dev) (saa7134_boards[dev->board]) - #define card_in(dev,n) (saa7134_boards[dev->board].inputs[n]) -@@ -535,6 +538,8 @@ struct saa7134_mpeg_ops { - int (*init)(struct saa7134_dev *dev); - int (*fini)(struct saa7134_dev *dev); - void (*signal_change)(struct saa7134_dev *dev); -+ void (*irq_ts_done)(struct saa7134_dev *dev, -+ unsigned long status); - }; - - /* global device status */ -diff --git a/drivers/staging/media/go7007/Makefile b/drivers/staging/media/go7007/Makefile -index 9c6ad4a..1b23689 100644 ---- a/drivers/staging/media/go7007/Makefile -+++ b/drivers/staging/media/go7007/Makefile -@@ -8,8 +8,7 @@ go7007-y := go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \ - - s2250-y := s2250-board.o - --# Uncomment when the saa7134 patches get into upstream --#obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o --#ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/pci/saa7134 -+obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o -+ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/pci/saa7134 - - ccflags-$(CONFIG_VIDEO_GO7007_LOADER:m=y) += -Idrivers/media/common diff --git a/drivers/staging/media/go7007/go7007-driver.c b/drivers/staging/media/go7007/go7007-driver.c deleted file mode 100644 index 6f1beca86b2b..000000000000 --- a/drivers/staging/media/go7007/go7007-driver.c +++ /dev/null @@ -1,711 +0,0 @@ -/* - * Copyright (C) 2005-2006 Micronas USA Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * 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/delay.h> -#include <linux/sched.h> -#include <linux/spinlock.h> -#include <linux/unistd.h> -#include <linux/time.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <linux/device.h> -#include <linux/i2c.h> -#include <linux/firmware.h> -#include <linux/mutex.h> -#include <linux/uaccess.h> -#include <linux/slab.h> -#include <linux/videodev2.h> -#include <media/tuner.h> -#include <media/v4l2-common.h> - -#include "go7007-priv.h" - -/* - * Wait for an interrupt to be delivered from the GO7007SB and return - * the associated value and data. - * - * Must be called with the hw_lock held. - */ -int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data) -{ - go->interrupt_available = 0; - go->hpi_ops->read_interrupt(go); - if (wait_event_timeout(go->interrupt_waitq, - go->interrupt_available, 5*HZ) < 0) { - v4l2_err(&go->v4l2_dev, "timeout waiting for read interrupt\n"); - return -1; - } - if (!go->interrupt_available) - return -1; - go->interrupt_available = 0; - *value = go->interrupt_value & 0xfffe; - *data = go->interrupt_data; - return 0; -} -EXPORT_SYMBOL(go7007_read_interrupt); - -/* - * Read a register/address on the GO7007SB. - * - * Must be called with the hw_lock held. - */ -int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data) -{ - int count = 100; - u16 value; - - if (go7007_write_interrupt(go, 0x0010, addr) < 0) - return -EIO; - while (count-- > 0) { - if (go7007_read_interrupt(go, &value, data) == 0 && - value == 0xa000) - return 0; - } - return -EIO; -} -EXPORT_SYMBOL(go7007_read_addr); - -/* - * Send the boot firmware to the encoder, which just wakes it up and lets - * us talk to the GPIO pins and on-board I2C adapter. - * - * Must be called with the hw_lock held. - */ -static int go7007_load_encoder(struct go7007 *go) -{ - const struct firmware *fw_entry; - char fw_name[] = "go7007/go7007fw.bin"; - void *bounce; - int fw_len, rv = 0; - u16 intr_val, intr_data; - - if (go->boot_fw == NULL) { - if (request_firmware(&fw_entry, fw_name, go->dev)) { - v4l2_err(go, "unable to load firmware from file \"%s\"\n", fw_name); - return -1; - } - if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) { - v4l2_err(go, "file \"%s\" does not appear to be go7007 firmware\n", fw_name); - release_firmware(fw_entry); - return -1; - } - fw_len = fw_entry->size - 16; - bounce = kmemdup(fw_entry->data + 16, fw_len, GFP_KERNEL); - if (bounce == NULL) { - v4l2_err(go, "unable to allocate %d bytes for firmware transfer\n", fw_len); - release_firmware(fw_entry); - return -1; - } - release_firmware(fw_entry); - go->boot_fw_len = fw_len; - go->boot_fw = bounce; - } - if (go7007_interface_reset(go) < 0 || - go7007_send_firmware(go, go->boot_fw, go->boot_fw_len) < 0 || - go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || - (intr_val & ~0x1) != 0x5a5a) { - v4l2_err(go, "error transferring firmware\n"); - rv = -1; - } - return rv; -} - -MODULE_FIRMWARE("go7007/go7007fw.bin"); - -/* - * Boot the encoder and register the I2C adapter if requested. Do the - * minimum initialization necessary, since the board-specific code may - * still need to probe the board ID. - * - * Must NOT be called with the hw_lock held. - */ -int go7007_boot_encoder(struct go7007 *go, int init_i2c) -{ - int ret; - - mutex_lock(&go->hw_lock); - ret = go7007_load_encoder(go); - mutex_unlock(&go->hw_lock); - if (ret < 0) - return -1; - if (!init_i2c) - return 0; - if (go7007_i2c_init(go) < 0) - return -1; - go->i2c_adapter_online = 1; - return 0; -} -EXPORT_SYMBOL(go7007_boot_encoder); - -/* - * Configure any hardware-related registers in the GO7007, such as GPIO - * pins and bus parameters, which are board-specific. This assumes - * the boot firmware has already been downloaded. - * - * Must be called with the hw_lock held. - */ -static int go7007_init_encoder(struct go7007 *go) -{ - if (go->board_info->audio_flags & GO7007_AUDIO_I2S_MASTER) { - go7007_write_addr(go, 0x1000, 0x0811); - go7007_write_addr(go, 0x1000, 0x0c11); - } - switch (go->board_id) { - case GO7007_BOARDID_MATRIX_REV: - /* Set GPIO pin 0 to be an output (audio clock control) */ - go7007_write_addr(go, 0x3c82, 0x0001); - go7007_write_addr(go, 0x3c80, 0x00fe); - break; - case GO7007_BOARDID_ADLINK_MPG24: - /* set GPIO5 to be an output, currently low */ - go7007_write_addr(go, 0x3c82, 0x0000); - go7007_write_addr(go, 0x3c80, 0x00df); - break; - case GO7007_BOARDID_ADS_USBAV_709: - /* GPIO pin 0: audio clock control */ - /* pin 2: TW9906 reset */ - /* pin 3: capture LED */ - go7007_write_addr(go, 0x3c82, 0x000d); - go7007_write_addr(go, 0x3c80, 0x00f2); - break; - } - return 0; -} - -/* - * Send the boot firmware to the GO7007 and configure the registers. This - * is the only way to stop the encoder once it has started streaming video. - * - * Must be called with the hw_lock held. - */ -int go7007_reset_encoder(struct go7007 *go) -{ - if (go7007_load_encoder(go) < 0) - return -1; - return go7007_init_encoder(go); -} - -/* - * Attempt to instantiate an I2C client by ID, probably loading a module. - */ -static int init_i2c_module(struct i2c_adapter *adapter, const struct go_i2c *const i2c) -{ - struct go7007 *go = i2c_get_adapdata(adapter); - struct v4l2_device *v4l2_dev = &go->v4l2_dev; - struct v4l2_subdev *sd; - struct i2c_board_info info; - - memset(&info, 0, sizeof(info)); - strlcpy(info.type, i2c->type, sizeof(info.type)); - info.addr = i2c->addr; - info.flags = i2c->flags; - - sd = v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, NULL); - if (sd) { - if (i2c->is_video) - go->sd_video = sd; - if (i2c->is_audio) - go->sd_audio = sd; - return 0; - } - - printk(KERN_INFO "go7007: probing for module i2c:%s failed\n", i2c->type); - return -EINVAL; -} - -/* - * Detach and unregister the encoder. The go7007 struct won't be freed - * until v4l2 finishes releasing its resources and all associated fds are - * closed by applications. - */ -static void go7007_remove(struct v4l2_device *v4l2_dev) -{ - struct go7007 *go = container_of(v4l2_dev, struct go7007, v4l2_dev); - - v4l2_device_unregister(v4l2_dev); - if (go->hpi_ops->release) - go->hpi_ops->release(go); - if (go->i2c_adapter_online) { - i2c_del_adapter(&go->i2c_adapter); - go->i2c_adapter_online = 0; - } - - kfree(go->boot_fw); - go7007_v4l2_remove(go); - kfree(go); -} - -/* - * Finalize the GO7007 hardware setup, register the on-board I2C adapter - * (if used on this board), load the I2C client driver for the sensor - * (SAA7115 or whatever) and other devices, and register the ALSA and V4L2 - * interfaces. - * - * Must NOT be called with the hw_lock held. - */ -int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs) -{ - int i, ret; - - dev_info(go->dev, "go7007: registering new %s\n", go->name); - - go->v4l2_dev.release = go7007_remove; - ret = v4l2_device_register(go->dev, &go->v4l2_dev); - if (ret < 0) - return ret; - - mutex_lock(&go->hw_lock); - ret = go7007_init_encoder(go); - mutex_unlock(&go->hw_lock); - if (ret < 0) - return ret; - - ret = go7007_v4l2_ctrl_init(go); - if (ret < 0) - return ret; - - if (!go->i2c_adapter_online && - go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) { - ret = go7007_i2c_init(go); - if (ret < 0) - return ret; - go->i2c_adapter_online = 1; - } - if (go->i2c_adapter_online) { - if (go->board_id == GO7007_BOARDID_ADS_USBAV_709) { - /* Reset the TW9906 */ - go7007_write_addr(go, 0x3c82, 0x0009); - msleep(50); - go7007_write_addr(go, 0x3c82, 0x000d); - } - for (i = 0; i < num_i2c_devs; ++i) - init_i2c_module(&go->i2c_adapter, &go->board_info->i2c_devs[i]); - - if (go->tuner_type >= 0) { - struct tuner_setup setup = { - .addr = ADDR_UNSET, - .type = go->tuner_type, - .mode_mask = T_ANALOG_TV, - }; - - v4l2_device_call_all(&go->v4l2_dev, 0, tuner, - s_type_addr, &setup); - } - if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) - v4l2_subdev_call(go->sd_video, video, s_routing, - 0, 0, go->channel_number + 1); - } - - ret = go7007_v4l2_init(go); - if (ret < 0) - return ret; - - if (go->board_info->flags & GO7007_BOARD_HAS_AUDIO) { - go->audio_enabled = 1; - go7007_snd_init(go); - } - return 0; -} -EXPORT_SYMBOL(go7007_register_encoder); - -/* - * Send the encode firmware to the encoder, which will cause it - * to immediately start delivering the video and audio streams. - * - * Must be called with the hw_lock held. - */ -int go7007_start_encoder(struct go7007 *go) -{ - u8 *fw; - int fw_len, rv = 0, i; - u16 intr_val, intr_data; - - go->modet_enable = 0; - if (!go->dvd_mode) - for (i = 0; i < 4; ++i) { - if (go->modet[i].enable) { - go->modet_enable = 1; - continue; - } - go->modet[i].pixel_threshold = 32767; - go->modet[i].motion_threshold = 32767; - go->modet[i].mb_threshold = 32767; - } - - if (go7007_construct_fw_image(go, &fw, &fw_len) < 0) - return -1; - - if (go7007_send_firmware(go, fw, fw_len) < 0 || - go7007_read_interrupt(go, &intr_val, &intr_data) < 0) { - v4l2_err(&go->v4l2_dev, "error transferring firmware\n"); - rv = -1; - goto start_error; - } - - go->state = STATE_DATA; - go->parse_length = 0; - go->seen_frame = 0; - if (go7007_stream_start(go) < 0) { - v4l2_err(&go->v4l2_dev, "error starting stream transfer\n"); - rv = -1; - goto start_error; - } - -start_error: - kfree(fw); - return rv; -} - -/* - * Store a byte in the current video buffer, if there is one. - */ -static inline void store_byte(struct go7007_buffer *vb, u8 byte) -{ - if (vb && vb->vb.v4l2_planes[0].bytesused < GO7007_BUF_SIZE) { - u8 *ptr = vb2_plane_vaddr(&vb->vb, 0); - - ptr[vb->vb.v4l2_planes[0].bytesused++] = byte; - } -} - -/* - * Deliver the last video buffer and get a new one to start writing to. - */ -static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb) -{ - struct go7007_buffer *vb_tmp = NULL; - u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused; - int i; - - if (vb) { - if (vb->modet_active) { - if (*bytesused + 216 < GO7007_BUF_SIZE) { - for (i = 0; i < 216; ++i) - store_byte(vb, go->active_map[i]); - *bytesused -= 216; - } else - vb->modet_active = 0; - } - vb->vb.v4l2_buf.sequence = go->next_seq++; - v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp); - vb_tmp = vb; - spin_lock(&go->spinlock); - list_del(&vb->list); - if (list_empty(&go->vidq_active)) - vb = NULL; - else - vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list); - go->active_buf = vb; - spin_unlock(&go->spinlock); - vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE); - return vb; - } - spin_lock(&go->spinlock); - if (!list_empty(&go->vidq_active)) - vb = go->active_buf = - list_first_entry(&go->vidq_active, struct go7007_buffer, list); - spin_unlock(&go->spinlock); - go->next_seq++; - return vb; -} - -static void write_bitmap_word(struct go7007 *go) -{ - int x, y, i, stride = ((go->width >> 4) + 7) >> 3; - - for (i = 0; i < 16; ++i) { - y = (((go->parse_length - 1) << 3) + i) / (go->width >> 4); - x = (((go->parse_length - 1) << 3) + i) % (go->width >> 4); - if (stride * y + (x >> 3) < sizeof(go->active_map)) - go->active_map[stride * y + (x >> 3)] |= - (go->modet_word & 1) << (x & 0x7); - go->modet_word >>= 1; - } -} - -/* - * Parse a chunk of the video stream into frames. The frames are not - * delimited by the hardware, so we have to parse the frame boundaries - * based on the type of video stream we're receiving. - */ -void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) -{ - struct go7007_buffer *vb = go->active_buf; - int i, seq_start_code = -1, gop_start_code = -1, frame_start_code = -1; - - switch (go->format) { - case V4L2_PIX_FMT_MPEG4: - seq_start_code = 0xB0; - gop_start_code = 0xB3; - frame_start_code = 0xB6; - break; - case V4L2_PIX_FMT_MPEG1: - case V4L2_PIX_FMT_MPEG2: - seq_start_code = 0xB3; - gop_start_code = 0xB8; - frame_start_code = 0x00; - break; - } - - for (i = 0; i < length; ++i) { - if (vb && vb->vb.v4l2_planes[0].bytesused >= GO7007_BUF_SIZE - 3) { - v4l2_info(&go->v4l2_dev, "dropping oversized frame\n"); - vb->vb.v4l2_planes[0].bytesused = 0; - vb->frame_offset = 0; - vb->modet_active = 0; - vb = go->active_buf = NULL; - } - - switch (go->state) { - case STATE_DATA: - switch (buf[i]) { - case 0x00: - go->state = STATE_00; - break; - case 0xFF: - go->state = STATE_FF; - break; - default: - store_byte(vb, buf[i]); - break; - } - break; - case STATE_00: - switch (buf[i]) { - case 0x00: - go->state = STATE_00_00; - break; - case 0xFF: - store_byte(vb, 0x00); - go->state = STATE_FF; - break; - default: - store_byte(vb, 0x00); - store_byte(vb, buf[i]); - go->state = STATE_DATA; - break; - } - break; - case STATE_00_00: - switch (buf[i]) { - case 0x00: - store_byte(vb, 0x00); - /* go->state remains STATE_00_00 */ - break; - case 0x01: - go->state = STATE_00_00_01; - break; - case 0xFF: - store_byte(vb, 0x00); - store_byte(vb, 0x00); - go->state = STATE_FF; - break; - default: - store_byte(vb, 0x00); - store_byte(vb, 0x00); - store_byte(vb, buf[i]); - go->state = STATE_DATA; - break; - } - break; - case STATE_00_00_01: - if (buf[i] == 0xF8 && go->modet_enable == 0) { - /* MODET start code, but MODET not enabled */ - store_byte(vb, 0x00); - store_byte(vb, 0x00); - store_byte(vb, 0x01); - store_byte(vb, 0xF8); - go->state = STATE_DATA; - break; - } - /* If this is the start of a new MPEG frame, - * get a new buffer */ - if ((go->format == V4L2_PIX_FMT_MPEG1 || - go->format == V4L2_PIX_FMT_MPEG2 || - go->format == V4L2_PIX_FMT_MPEG4) && - (buf[i] == seq_start_code || - buf[i] == gop_start_code || - buf[i] == frame_start_code)) { - if (vb == NULL || go->seen_frame) - vb = frame_boundary(go, vb); - go->seen_frame = buf[i] == frame_start_code; - if (vb && go->seen_frame) - vb->frame_offset = vb->vb.v4l2_planes[0].bytesused; - } - /* Handle any special chunk types, or just write the - * start code to the (potentially new) buffer */ - switch (buf[i]) { - case 0xF5: /* timestamp */ - go->parse_length = 12; - go->state = STATE_UNPARSED; - break; - case 0xF6: /* vbi */ - go->state = STATE_VBI_LEN_A; - break; - case 0xF8: /* MD map */ - go->parse_length = 0; - memset(go->active_map, 0, - sizeof(go->active_map)); - go->state = STATE_MODET_MAP; - break; - case 0xFF: /* Potential JPEG start code */ - store_byte(vb, 0x00); - store_byte(vb, 0x00); - store_byte(vb, 0x01); - go->state = STATE_FF; - break; - default: - store_byte(vb, 0x00); - store_byte(vb, 0x00); - store_byte(vb, 0x01); - store_byte(vb, buf[i]); - go->state = STATE_DATA; - break; - } - break; - case STATE_FF: - switch (buf[i]) { - case 0x00: - store_byte(vb, 0xFF); - go->state = STATE_00; - break; - case 0xFF: - store_byte(vb, 0xFF); - /* go->state remains STATE_FF */ - break; - case 0xD8: - if (go->format == V4L2_PIX_FMT_MJPEG) - vb = frame_boundary(go, vb); - /* fall through */ - default: - store_byte(vb, 0xFF); - store_byte(vb, buf[i]); - go->state = STATE_DATA; - break; - } - break; - case STATE_VBI_LEN_A: - go->parse_length = buf[i] << 8; - go->state = STATE_VBI_LEN_B; - break; - case STATE_VBI_LEN_B: - go->parse_length |= buf[i]; - if (go->parse_length > 0) - go->state = STATE_UNPARSED; - else - go->state = STATE_DATA; - break; - case STATE_MODET_MAP: - if (go->parse_length < 204) { - if (go->parse_length & 1) { - go->modet_word |= buf[i]; - write_bitmap_word(go); - } else - go->modet_word = buf[i] << 8; - } else if (go->parse_length == 207 && vb) { - vb->modet_active = buf[i]; - } - if (++go->parse_length == 208) - go->state = STATE_DATA; - break; - case STATE_UNPARSED: - if (--go->parse_length == 0) - go->state = STATE_DATA; - break; - } - } -} -EXPORT_SYMBOL(go7007_parse_video_stream); - -/* - * Allocate a new go7007 struct. Used by the hardware-specific probe. - */ -struct go7007 *go7007_alloc(const struct go7007_board_info *board, - struct device *dev) -{ - struct go7007 *go; - int i; - - go = kzalloc(sizeof(struct go7007), GFP_KERNEL); - if (go == NULL) - return NULL; - go->dev = dev; - go->board_info = board; - go->board_id = 0; - go->tuner_type = -1; - go->channel_number = 0; - go->name[0] = 0; - mutex_init(&go->hw_lock); - init_waitqueue_head(&go->frame_waitq); - spin_lock_init(&go->spinlock); - go->status = STATUS_INIT; - memset(&go->i2c_adapter, 0, sizeof(go->i2c_adapter)); - go->i2c_adapter_online = 0; - go->interrupt_available = 0; - init_waitqueue_head(&go->interrupt_waitq); - go->input = 0; - go7007_update_board(go); - go->encoder_h_halve = 0; - go->encoder_v_halve = 0; - go->encoder_subsample = 0; - go->format = V4L2_PIX_FMT_MJPEG; - go->bitrate = 1500000; - go->fps_scale = 1; - go->pali = 0; - go->aspect_ratio = GO7007_RATIO_1_1; - go->gop_size = 0; - go->ipb = 0; - go->closed_gop = 0; - go->repeat_seqhead = 0; - go->seq_header_enable = 0; - go->gop_header_enable = 0; - go->dvd_mode = 0; - go->interlace_coding = 0; - for (i = 0; i < 4; ++i) - go->modet[i].enable = 0; - for (i = 0; i < 1624; ++i) - go->modet_map[i] = 0; - go->audio_deliver = NULL; - go->audio_enabled = 0; - - return go; -} -EXPORT_SYMBOL(go7007_alloc); - -void go7007_update_board(struct go7007 *go) -{ - const struct go7007_board_info *board = go->board_info; - - if (board->sensor_flags & GO7007_SENSOR_TV) { - go->standard = GO7007_STD_NTSC; - go->std = V4L2_STD_NTSC_M; - go->width = 720; - go->height = 480; - go->sensor_framerate = 30000; - } else { - go->standard = GO7007_STD_OTHER; - go->width = board->sensor_width; - go->height = board->sensor_height; - go->sensor_framerate = board->sensor_framerate; - } - go->encoder_v_offset = board->sensor_v_offset; - go->encoder_h_offset = board->sensor_h_offset; -} -EXPORT_SYMBOL(go7007_update_board); - -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/media/go7007/go7007-fw.c b/drivers/staging/media/go7007/go7007-fw.c deleted file mode 100644 index 814ce08bc44d..000000000000 --- a/drivers/staging/media/go7007/go7007-fw.c +++ /dev/null @@ -1,1628 +0,0 @@ -/* - * Copyright (C) 2005-2006 Micronas USA Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * 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 contains code to generate a firmware image for the GO7007SB - * encoder. Much of the firmware is read verbatim from a file, but some of - * it concerning bitrate control and other things that can be configured at - * run-time are generated dynamically. Note that the format headers - * generated here do not affect the functioning of the encoder; they are - * merely parroted back to the host at the start of each frame. - */ - -#include <linux/module.h> -#include <linux/time.h> -#include <linux/mm.h> -#include <linux/device.h> -#include <linux/i2c.h> -#include <linux/firmware.h> -#include <linux/slab.h> -#include <asm/byteorder.h> - -#include "go7007-priv.h" - -#define GO7007_FW_NAME "go7007/go7007tv.bin" - -/* Constants used in the source firmware image to describe code segments */ - -#define FLAG_MODE_MJPEG (1) -#define FLAG_MODE_MPEG1 (1<<1) -#define FLAG_MODE_MPEG2 (1<<2) -#define FLAG_MODE_MPEG4 (1<<3) -#define FLAG_MODE_H263 (1<<4) -#define FLAG_MODE_ALL (FLAG_MODE_MJPEG | FLAG_MODE_MPEG1 | \ - FLAG_MODE_MPEG2 | FLAG_MODE_MPEG4 | \ - FLAG_MODE_H263) -#define FLAG_SPECIAL (1<<8) - -#define SPECIAL_FRM_HEAD 0 -#define SPECIAL_BRC_CTRL 1 -#define SPECIAL_CONFIG 2 -#define SPECIAL_SEQHEAD 3 -#define SPECIAL_AV_SYNC 4 -#define SPECIAL_FINAL 5 -#define SPECIAL_AUDIO 6 -#define SPECIAL_MODET 7 - -/* Little data class for creating MPEG headers bit-by-bit */ - -struct code_gen { - unsigned char *p; /* destination */ - u32 a; /* collects bits at the top of the variable */ - int b; /* bit position of most recently-written bit */ - int len; /* written out so far */ -}; - -#define CODE_GEN(name, dest) struct code_gen name = { dest, 0, 32, 0 } - -#define CODE_ADD(name, val, length) do { \ - name.b -= (length); \ - name.a |= (val) << name.b; \ - while (name.b <= 24) { \ - *name.p = name.a >> 24; \ - ++name.p; \ - name.a <<= 8; \ - name.b += 8; \ - name.len += 8; \ - } \ -} while (0) - -#define CODE_LENGTH(name) (name.len + (32 - name.b)) - -/* Tables for creating the bitrate control data */ - -static const s16 converge_speed_ip[101] = { - 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, 1, 1, 1, 1, 1, 1, 1, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, - 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, - 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, - 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, - 19, 20, 22, 23, 25, 27, 30, 32, 35, 38, - 41, 45, 49, 53, 58, 63, 69, 76, 83, 91, - 100 -}; - -static const s16 converge_speed_ipb[101] = { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, - 6, 6, 6, 7, 7, 7, 7, 8, 8, 9, - 9, 9, 10, 10, 11, 12, 12, 13, 14, 14, - 15, 16, 17, 18, 19, 20, 22, 23, 25, 26, - 28, 30, 32, 34, 37, 40, 42, 46, 49, 53, - 57, 61, 66, 71, 77, 83, 90, 97, 106, 115, - 125, 135, 147, 161, 175, 191, 209, 228, 249, 273, - 300 -}; - -static const s16 LAMBDA_table[4][101] = { - { 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, - 19, 19, 19, 20, 20, 20, 21, 21, 22, 22, - 22, 23, 23, 24, 24, 25, 25, 25, 26, 26, - 27, 27, 28, 28, 29, 29, 30, 31, 31, 32, - 32, 33, 33, 34, 35, 35, 36, 37, 37, 38, - 39, 39, 40, 41, 42, 42, 43, 44, 45, 46, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, - 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, - 96 - }, - { - 20, 20, 20, 21, 21, 21, 22, 22, 23, 23, - 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, - 28, 29, 29, 30, 30, 31, 31, 32, 33, 33, - 34, 34, 35, 36, 36, 37, 38, 38, 39, 40, - 40, 41, 42, 43, 43, 44, 45, 46, 47, 48, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 64, 65, 66, 67, 68, - 70, 71, 72, 73, 75, 76, 78, 79, 80, 82, - 83, 85, 86, 88, 90, 91, 93, 95, 96, 98, - 100, 102, 103, 105, 107, 109, 111, 113, 115, 117, - 120 - }, - { - 24, 24, 24, 25, 25, 26, 26, 27, 27, 28, - 28, 29, 29, 30, 30, 31, 31, 32, 33, 33, - 34, 34, 35, 36, 36, 37, 38, 38, 39, 40, - 41, 41, 42, 43, 44, 44, 45, 46, 47, 48, - 49, 50, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 62, 63, 64, 65, 66, 67, 69, - 70, 71, 72, 74, 75, 76, 78, 79, 81, 82, - 84, 85, 87, 88, 90, 92, 93, 95, 97, 98, - 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, - 120, 122, 124, 127, 129, 131, 134, 136, 138, 141, - 144 - }, - { - 32, 32, 33, 33, 34, 34, 35, 36, 36, 37, - 38, 38, 39, 40, 41, 41, 42, 43, 44, 44, - 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 62, 63, 64, - 65, 66, 67, 69, 70, 71, 72, 74, 75, 76, - 78, 79, 81, 82, 84, 85, 87, 88, 90, 92, - 93, 95, 97, 98, 100, 102, 104, 106, 108, 110, - 112, 114, 116, 118, 120, 122, 124, 127, 129, 131, - 134, 136, 139, 141, 144, 146, 149, 152, 154, 157, - 160, 163, 166, 169, 172, 175, 178, 181, 185, 188, - 192 - } -}; - -/* MPEG blank frame generation tables */ - -enum mpeg_frame_type { - PFRAME, - BFRAME_PRE, - BFRAME_POST, - BFRAME_BIDIR, - BFRAME_EMPTY -}; - -static const u32 addrinctab[33][2] = { - { 0x01, 1 }, { 0x03, 3 }, { 0x02, 3 }, { 0x03, 4 }, - { 0x02, 4 }, { 0x03, 5 }, { 0x02, 5 }, { 0x07, 7 }, - { 0x06, 7 }, { 0x0b, 8 }, { 0x0a, 8 }, { 0x09, 8 }, - { 0x08, 8 }, { 0x07, 8 }, { 0x06, 8 }, { 0x17, 10 }, - { 0x16, 10 }, { 0x15, 10 }, { 0x14, 10 }, { 0x13, 10 }, - { 0x12, 10 }, { 0x23, 11 }, { 0x22, 11 }, { 0x21, 11 }, - { 0x20, 11 }, { 0x1f, 11 }, { 0x1e, 11 }, { 0x1d, 11 }, - { 0x1c, 11 }, { 0x1b, 11 }, { 0x1a, 11 }, { 0x19, 11 }, - { 0x18, 11 } -}; - -/* Standard JPEG tables */ - -static const u8 default_intra_quant_table[] = { - 8, 16, 19, 22, 26, 27, 29, 34, - 16, 16, 22, 24, 27, 29, 34, 37, - 19, 22, 26, 27, 29, 34, 34, 38, - 22, 22, 26, 27, 29, 34, 37, 40, - 22, 26, 27, 29, 32, 35, 40, 48, - 26, 27, 29, 32, 35, 40, 48, 58, - 26, 27, 29, 34, 38, 46, 56, 69, - 27, 29, 35, 38, 46, 56, 69, 83 -}; - -static const u8 bits_dc_luminance[] = { - 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 -}; - -static const u8 val_dc_luminance[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 -}; - -static const u8 bits_dc_chrominance[] = { - 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 -}; - -static const u8 val_dc_chrominance[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 -}; - -static const u8 bits_ac_luminance[] = { - 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d -}; - -static const u8 val_ac_luminance[] = { - 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, - 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, - 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, - 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, - 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa -}; - -static const u8 bits_ac_chrominance[] = { - 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 -}; - -static const u8 val_ac_chrominance[] = { - 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, - 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, - 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, - 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, - 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, - 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, - 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, - 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, - 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, - 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa -}; - -/* Zig-zag mapping for quant table - * - * OK, let's do this mapping on the actual table above so it doesn't have - * to be done on the fly. - */ -static const int zz[64] = { - 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 -}; - -static int copy_packages(__le16 *dest, u16 *src, int pkg_cnt, int space) -{ - int i, cnt = pkg_cnt * 32; - - if (space < cnt) - return -1; - - for (i = 0; i < cnt; ++i) - dest[i] = cpu_to_le16p(src + i); - - return cnt; -} - -static int mjpeg_frame_header(struct go7007 *go, unsigned char *buf, int q) -{ - int i, p = 0; - - buf[p++] = 0xff; - buf[p++] = 0xd8; - buf[p++] = 0xff; - buf[p++] = 0xdb; - buf[p++] = 0; - buf[p++] = 2 + 65; - buf[p++] = 0; - buf[p++] = default_intra_quant_table[0]; - for (i = 1; i < 64; ++i) - /* buf[p++] = (default_intra_quant_table[i] * q) >> 3; */ - buf[p++] = (default_intra_quant_table[zz[i]] * q) >> 3; - buf[p++] = 0xff; - buf[p++] = 0xc0; - buf[p++] = 0; - buf[p++] = 17; - buf[p++] = 8; - buf[p++] = go->height >> 8; - buf[p++] = go->height & 0xff; - buf[p++] = go->width >> 8; - buf[p++] = go->width & 0xff; - buf[p++] = 3; - buf[p++] = 1; - buf[p++] = 0x22; - buf[p++] = 0; - buf[p++] = 2; - buf[p++] = 0x11; - buf[p++] = 0; - buf[p++] = 3; - buf[p++] = 0x11; - buf[p++] = 0; - buf[p++] = 0xff; - buf[p++] = 0xc4; - buf[p++] = 418 >> 8; - buf[p++] = 418 & 0xff; - buf[p++] = 0x00; - memcpy(buf + p, bits_dc_luminance + 1, 16); - p += 16; - memcpy(buf + p, val_dc_luminance, sizeof(val_dc_luminance)); - p += sizeof(val_dc_luminance); - buf[p++] = 0x01; - memcpy(buf + p, bits_dc_chrominance + 1, 16); - p += 16; - memcpy(buf + p, val_dc_chrominance, sizeof(val_dc_chrominance)); - p += sizeof(val_dc_chrominance); - buf[p++] = 0x10; - memcpy(buf + p, bits_ac_luminance + 1, 16); - p += 16; - memcpy(buf + p, val_ac_luminance, sizeof(val_ac_luminance)); - p += sizeof(val_ac_luminance); - buf[p++] = 0x11; - memcpy(buf + p, bits_ac_chrominance + 1, 16); - p += 16; - memcpy(buf + p, val_ac_chrominance, sizeof(val_ac_chrominance)); - p += sizeof(val_ac_chrominance); - buf[p++] = 0xff; - buf[p++] = 0xda; - buf[p++] = 0; - buf[p++] = 12; - buf[p++] = 3; - buf[p++] = 1; - buf[p++] = 0x00; - buf[p++] = 2; - buf[p++] = 0x11; - buf[p++] = 3; - buf[p++] = 0x11; - buf[p++] = 0; - buf[p++] = 63; - buf[p++] = 0; - return p; -} - -static int gen_mjpeghdr_to_package(struct go7007 *go, __le16 *code, int space) -{ - u8 *buf; - u16 mem = 0x3e00; - unsigned int addr = 0x19; - int size = 0, i, off = 0, chunk; - - buf = kzalloc(4096, GFP_KERNEL); - if (buf == NULL) - return -1; - - for (i = 1; i < 32; ++i) { - mjpeg_frame_header(go, buf + size, i); - size += 80; - } - chunk = mjpeg_frame_header(go, buf + size, 1); - memmove(buf + size, buf + size + 80, chunk - 80); - size += chunk - 80; - - for (i = 0; i < size; i += chunk * 2) { - if (space - off < 32) { - off = -1; - goto done; - } - - code[off + 1] = __cpu_to_le16(0x8000 | mem); - - chunk = 28; - if (mem + chunk > 0x4000) - chunk = 0x4000 - mem; - if (i + 2 * chunk > size) - chunk = (size - i) / 2; - - if (chunk < 28) { - code[off] = __cpu_to_le16(0x4000 | chunk); - code[off + 31] = __cpu_to_le16(addr++); - mem = 0x3e00; - } else { - code[off] = __cpu_to_le16(0x1000 | 28); - code[off + 31] = 0; - mem += 28; - } - - memcpy(&code[off + 2], buf + i, chunk * 2); - off += 32; - } -done: - kfree(buf); - return off; -} - -static int mpeg1_frame_header(struct go7007 *go, unsigned char *buf, - int modulo, int pict_struct, enum mpeg_frame_type frame) -{ - int i, j, mb_code, mb_len; - int rows = go->interlace_coding ? go->height / 32 : go->height / 16; - CODE_GEN(c, buf + 6); - - switch (frame) { - case PFRAME: - mb_code = 0x1; - mb_len = 3; - break; - case BFRAME_PRE: - mb_code = 0x2; - mb_len = 4; - break; - case BFRAME_POST: - mb_code = 0x2; - mb_len = 3; - break; - case BFRAME_BIDIR: - mb_code = 0x2; - mb_len = 2; - break; - default: /* keep the compiler happy */ - mb_code = mb_len = 0; - break; - } - - CODE_ADD(c, frame == PFRAME ? 0x2 : 0x3, 13); - CODE_ADD(c, 0xffff, 16); - CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4); - if (frame != PFRAME) - CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4); - else - CODE_ADD(c, 0, 4); /* Is this supposed to be here?? */ - CODE_ADD(c, 0, 3); /* What is this?? */ - /* Byte-align with zeros */ - j = 8 - (CODE_LENGTH(c) % 8); - if (j != 8) - CODE_ADD(c, 0, j); - - if (go->format == V4L2_PIX_FMT_MPEG2) { - CODE_ADD(c, 0x1, 24); - CODE_ADD(c, 0xb5, 8); - CODE_ADD(c, 0x844, 12); - CODE_ADD(c, frame == PFRAME ? 0xff : 0x44, 8); - if (go->interlace_coding) { - CODE_ADD(c, pict_struct, 4); - if (go->dvd_mode) - CODE_ADD(c, 0x000, 11); - else - CODE_ADD(c, 0x200, 11); - } else { - CODE_ADD(c, 0x3, 4); - CODE_ADD(c, 0x20c, 11); - } - /* Byte-align with zeros */ - j = 8 - (CODE_LENGTH(c) % 8); - if (j != 8) - CODE_ADD(c, 0, j); - } - - for (i = 0; i < rows; ++i) { - CODE_ADD(c, 1, 24); - CODE_ADD(c, i + 1, 8); - CODE_ADD(c, 0x2, 6); - CODE_ADD(c, 0x1, 1); - CODE_ADD(c, mb_code, mb_len); - if (go->interlace_coding) { - CODE_ADD(c, 0x1, 2); - CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); - } - if (frame == BFRAME_BIDIR) { - CODE_ADD(c, 0x3, 2); - if (go->interlace_coding) - CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); - } - CODE_ADD(c, 0x3, 2); - for (j = (go->width >> 4) - 2; j >= 33; j -= 33) - CODE_ADD(c, 0x8, 11); - CODE_ADD(c, addrinctab[j][0], addrinctab[j][1]); - CODE_ADD(c, mb_code, mb_len); - if (go->interlace_coding) { - CODE_ADD(c, 0x1, 2); - CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); - } - if (frame == BFRAME_BIDIR) { - CODE_ADD(c, 0x3, 2); - if (go->interlace_coding) - CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); - } - CODE_ADD(c, 0x3, 2); - - /* Byte-align with zeros */ - j = 8 - (CODE_LENGTH(c) % 8); - if (j != 8) - CODE_ADD(c, 0, j); - } - - i = CODE_LENGTH(c) + 4 * 8; - buf[2] = 0x00; - buf[3] = 0x00; - buf[4] = 0x01; - buf[5] = 0x00; - return i; -} - -static int mpeg1_sequence_header(struct go7007 *go, unsigned char *buf, int ext) -{ - int i, aspect_ratio, picture_rate; - CODE_GEN(c, buf + 6); - - if (go->format == V4L2_PIX_FMT_MPEG1) { - switch (go->aspect_ratio) { - case GO7007_RATIO_4_3: - aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2; - break; - case GO7007_RATIO_16_9: - aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4; - break; - default: - aspect_ratio = 1; - break; - } - } else { - switch (go->aspect_ratio) { - case GO7007_RATIO_4_3: - aspect_ratio = 2; - break; - case GO7007_RATIO_16_9: - aspect_ratio = 3; - break; - default: - aspect_ratio = 1; - break; - } - } - switch (go->sensor_framerate) { - case 24000: - picture_rate = 1; - break; - case 24024: - picture_rate = 2; - break; - case 25025: - picture_rate = go->interlace_coding ? 6 : 3; - break; - case 30000: - picture_rate = go->interlace_coding ? 7 : 4; - break; - case 30030: - picture_rate = go->interlace_coding ? 8 : 5; - break; - default: - picture_rate = 5; /* 30 fps seems like a reasonable default */ - break; - } - - CODE_ADD(c, go->width, 12); - CODE_ADD(c, go->height, 12); - CODE_ADD(c, aspect_ratio, 4); - CODE_ADD(c, picture_rate, 4); - CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 20000 : 0x3ffff, 18); - CODE_ADD(c, 1, 1); - CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 112 : 20, 10); - CODE_ADD(c, 0, 3); - - /* Byte-align with zeros */ - i = 8 - (CODE_LENGTH(c) % 8); - if (i != 8) - CODE_ADD(c, 0, i); - - if (go->format == V4L2_PIX_FMT_MPEG2) { - CODE_ADD(c, 0x1, 24); - CODE_ADD(c, 0xb5, 8); - CODE_ADD(c, 0x148, 12); - if (go->interlace_coding) - CODE_ADD(c, 0x20001, 20); - else - CODE_ADD(c, 0xa0001, 20); - CODE_ADD(c, 0, 16); - - /* Byte-align with zeros */ - i = 8 - (CODE_LENGTH(c) % 8); - if (i != 8) - CODE_ADD(c, 0, i); - - if (ext) { - CODE_ADD(c, 0x1, 24); - CODE_ADD(c, 0xb52, 12); - CODE_ADD(c, go->standard == GO7007_STD_NTSC ? 2 : 1, 3); - CODE_ADD(c, 0x105, 9); - CODE_ADD(c, 0x505, 16); - CODE_ADD(c, go->width, 14); - CODE_ADD(c, 1, 1); - CODE_ADD(c, go->height, 14); - - /* Byte-align with zeros */ - i = 8 - (CODE_LENGTH(c) % 8); - if (i != 8) - CODE_ADD(c, 0, i); - } - } - - i = CODE_LENGTH(c) + 4 * 8; - buf[0] = i & 0xff; - buf[1] = i >> 8; - buf[2] = 0x00; - buf[3] = 0x00; - buf[4] = 0x01; - buf[5] = 0xb3; - return i; -} - -static int gen_mpeg1hdr_to_package(struct go7007 *go, - __le16 *code, int space, int *framelen) -{ - u8 *buf; - u16 mem = 0x3e00; - unsigned int addr = 0x19; - int i, off = 0, chunk; - - buf = kzalloc(5120, GFP_KERNEL); - if (buf == NULL) - return -1; - - framelen[0] = mpeg1_frame_header(go, buf, 0, 1, PFRAME); - if (go->interlace_coding) - framelen[0] += mpeg1_frame_header(go, buf + framelen[0] / 8, - 0, 2, PFRAME); - buf[0] = framelen[0] & 0xff; - buf[1] = framelen[0] >> 8; - i = 368; - framelen[1] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_PRE); - if (go->interlace_coding) - framelen[1] += mpeg1_frame_header(go, buf + i + framelen[1] / 8, - 0, 2, BFRAME_PRE); - buf[i] = framelen[1] & 0xff; - buf[i + 1] = framelen[1] >> 8; - i += 1632; - framelen[2] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_POST); - if (go->interlace_coding) - framelen[2] += mpeg1_frame_header(go, buf + i + framelen[2] / 8, - 0, 2, BFRAME_POST); - buf[i] = framelen[2] & 0xff; - buf[i + 1] = framelen[2] >> 8; - i += 1432; - framelen[3] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_BIDIR); - if (go->interlace_coding) - framelen[3] += mpeg1_frame_header(go, buf + i + framelen[3] / 8, - 0, 2, BFRAME_BIDIR); - buf[i] = framelen[3] & 0xff; - buf[i + 1] = framelen[3] >> 8; - i += 1632 + 16; - mpeg1_sequence_header(go, buf + i, 0); - i += 40; - for (i = 0; i < 5120; i += chunk * 2) { - if (space - off < 32) { - off = -1; - goto done; - } - - code[off + 1] = __cpu_to_le16(0x8000 | mem); - - chunk = 28; - if (mem + chunk > 0x4000) - chunk = 0x4000 - mem; - if (i + 2 * chunk > 5120) - chunk = (5120 - i) / 2; - - if (chunk < 28) { - code[off] = __cpu_to_le16(0x4000 | chunk); - code[off + 31] = __cpu_to_le16(addr); - if (mem + chunk == 0x4000) { - mem = 0x3e00; - ++addr; - } - } else { - code[off] = __cpu_to_le16(0x1000 | 28); - code[off + 31] = 0; - mem += 28; - } - - memcpy(&code[off + 2], buf + i, chunk * 2); - off += 32; - } -done: - kfree(buf); - return off; -} - -static int vti_bitlen(struct go7007 *go) -{ - unsigned int i, max_time_incr = go->sensor_framerate / go->fps_scale; - - for (i = 31; (max_time_incr & ((1 << i) - 1)) == max_time_incr; --i) - ; - return i + 1; -} - -static int mpeg4_frame_header(struct go7007 *go, unsigned char *buf, - int modulo, enum mpeg_frame_type frame) -{ - int i; - CODE_GEN(c, buf + 6); - int mb_count = (go->width >> 4) * (go->height >> 4); - - CODE_ADD(c, frame == PFRAME ? 0x1 : 0x2, 2); - if (modulo) - CODE_ADD(c, 0x1, 1); - CODE_ADD(c, 0x1, 2); - CODE_ADD(c, 0, vti_bitlen(go)); - CODE_ADD(c, 0x3, 2); - if (frame == PFRAME) - CODE_ADD(c, 0, 1); - CODE_ADD(c, 0xc, 11); - if (frame != PFRAME) - CODE_ADD(c, 0x4, 3); - if (frame != BFRAME_EMPTY) { - for (i = 0; i < mb_count; ++i) { - switch (frame) { - case PFRAME: - CODE_ADD(c, 0x1, 1); - break; - case BFRAME_PRE: - CODE_ADD(c, 0x47, 8); - break; - case BFRAME_POST: - CODE_ADD(c, 0x27, 7); - break; - case BFRAME_BIDIR: - CODE_ADD(c, 0x5f, 8); - break; - case BFRAME_EMPTY: /* keep compiler quiet */ - break; - } - } - } - - /* Byte-align with a zero followed by ones */ - i = 8 - (CODE_LENGTH(c) % 8); - CODE_ADD(c, 0, 1); - CODE_ADD(c, (1 << (i - 1)) - 1, i - 1); - - i = CODE_LENGTH(c) + 4 * 8; - buf[0] = i & 0xff; - buf[1] = i >> 8; - buf[2] = 0x00; - buf[3] = 0x00; - buf[4] = 0x01; - buf[5] = 0xb6; - return i; -} - -static int mpeg4_sequence_header(struct go7007 *go, unsigned char *buf, int ext) -{ - const unsigned char head[] = { 0x00, 0x00, 0x01, 0xb0, go->pali, - 0x00, 0x00, 0x01, 0xb5, 0x09, - 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x01, 0x20, }; - int i, aspect_ratio; - int fps = go->sensor_framerate / go->fps_scale; - CODE_GEN(c, buf + 2 + sizeof(head)); - - switch (go->aspect_ratio) { - case GO7007_RATIO_4_3: - aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2; - break; - case GO7007_RATIO_16_9: - aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4; - break; - default: - aspect_ratio = 1; - break; - } - - memcpy(buf + 2, head, sizeof(head)); - CODE_ADD(c, 0x191, 17); - CODE_ADD(c, aspect_ratio, 4); - CODE_ADD(c, 0x1, 4); - CODE_ADD(c, fps, 16); - CODE_ADD(c, 0x3, 2); - CODE_ADD(c, 1001, vti_bitlen(go)); - CODE_ADD(c, 1, 1); - CODE_ADD(c, go->width, 13); - CODE_ADD(c, 1, 1); - CODE_ADD(c, go->height, 13); - CODE_ADD(c, 0x2830, 14); - - /* Byte-align */ - i = 8 - (CODE_LENGTH(c) % 8); - CODE_ADD(c, 0, 1); - CODE_ADD(c, (1 << (i - 1)) - 1, i - 1); - - i = CODE_LENGTH(c) + sizeof(head) * 8; - buf[0] = i & 0xff; - buf[1] = i >> 8; - return i; -} - -static int gen_mpeg4hdr_to_package(struct go7007 *go, - __le16 *code, int space, int *framelen) -{ - u8 *buf; - u16 mem = 0x3e00; - unsigned int addr = 0x19; - int i, off = 0, chunk; - - buf = kzalloc(5120, GFP_KERNEL); - if (buf == NULL) - return -1; - - framelen[0] = mpeg4_frame_header(go, buf, 0, PFRAME); - i = 368; - framelen[1] = mpeg4_frame_header(go, buf + i, 0, BFRAME_PRE); - i += 1632; - framelen[2] = mpeg4_frame_header(go, buf + i, 0, BFRAME_POST); - i += 1432; - framelen[3] = mpeg4_frame_header(go, buf + i, 0, BFRAME_BIDIR); - i += 1632; - mpeg4_frame_header(go, buf + i, 0, BFRAME_EMPTY); - i += 16; - mpeg4_sequence_header(go, buf + i, 0); - i += 40; - for (i = 0; i < 5120; i += chunk * 2) { - if (space - off < 32) { - off = -1; - goto done; - } - - code[off + 1] = __cpu_to_le16(0x8000 | mem); - - chunk = 28; - if (mem + chunk > 0x4000) - chunk = 0x4000 - mem; - if (i + 2 * chunk > 5120) - chunk = (5120 - i) / 2; - - if (chunk < 28) { - code[off] = __cpu_to_le16(0x4000 | chunk); - code[off + 31] = __cpu_to_le16(addr); - if (mem + chunk == 0x4000) { - mem = 0x3e00; - ++addr; - } - } else { - code[off] = __cpu_to_le16(0x1000 | 28); - code[off + 31] = 0; - mem += 28; - } - - memcpy(&code[off + 2], buf + i, chunk * 2); - off += 32; - } - mem = 0x3e00; - addr = go->ipb ? 0x14f9 : 0x0af9; - memset(buf, 0, 5120); - framelen[4] = mpeg4_frame_header(go, buf, 1, PFRAME); - i = 368; - framelen[5] = mpeg4_frame_header(go, buf + i, 1, BFRAME_PRE); - i += 1632; - framelen[6] = mpeg4_frame_header(go, buf + i, 1, BFRAME_POST); - i += 1432; - framelen[7] = mpeg4_frame_header(go, buf + i, 1, BFRAME_BIDIR); - i += 1632; - mpeg4_frame_header(go, buf + i, 1, BFRAME_EMPTY); - i += 16; - for (i = 0; i < 5120; i += chunk * 2) { - if (space - off < 32) { - off = -1; - goto done; - } - - code[off + 1] = __cpu_to_le16(0x8000 | mem); - - chunk = 28; - if (mem + chunk > 0x4000) - chunk = 0x4000 - mem; - if (i + 2 * chunk > 5120) - chunk = (5120 - i) / 2; - - if (chunk < 28) { - code[off] = __cpu_to_le16(0x4000 | chunk); - code[off + 31] = __cpu_to_le16(addr); - if (mem + chunk == 0x4000) { - mem = 0x3e00; - ++addr; - } - } else { - code[off] = __cpu_to_le16(0x1000 | 28); - code[off + 31] = 0; - mem += 28; - } - - memcpy(&code[off + 2], buf + i, chunk * 2); - off += 32; - } -done: - kfree(buf); - return off; -} - -static int brctrl_to_package(struct go7007 *go, - __le16 *code, int space, int *framelen) -{ - int converge_speed = 0; - int lambda = (go->format == V4L2_PIX_FMT_MJPEG || go->dvd_mode) ? - 100 : 0; - int peak_rate = 6 * go->bitrate / 5; - int vbv_buffer = go->format == V4L2_PIX_FMT_MJPEG ? - go->bitrate : - (go->dvd_mode ? 900000 : peak_rate); - int fps = go->sensor_framerate / go->fps_scale; - int q = 0; - /* Bizarre math below depends on rounding errors in division */ - u32 sgop_expt_addr = go->bitrate / 32 * (go->ipb ? 3 : 1) * 1001 / fps; - u32 sgop_peak_addr = peak_rate / 32 * 1001 / fps; - u32 total_expt_addr = go->bitrate / 32 * 1000 / fps * (fps / 1000); - u32 vbv_alert_addr = vbv_buffer * 3 / (4 * 32); - u32 cplx[] = { - q > 0 ? sgop_expt_addr * q : - 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, - q > 0 ? sgop_expt_addr * q : - 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, - q > 0 ? sgop_expt_addr * q : - 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, - q > 0 ? sgop_expt_addr * q : - 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, - }; - u32 calc_q = q > 0 ? q : cplx[0] / sgop_expt_addr; - u16 pack[] = { - 0x200e, 0x0000, - 0xBF20, go->ipb ? converge_speed_ipb[converge_speed] - : converge_speed_ip[converge_speed], - 0xBF21, go->ipb ? 2 : 0, - 0xBF22, go->ipb ? LAMBDA_table[0][lambda / 2 + 50] - : 32767, - 0xBF23, go->ipb ? LAMBDA_table[1][lambda] : 32767, - 0xBF24, 32767, - 0xBF25, lambda > 99 ? 32767 : LAMBDA_table[3][lambda], - 0xBF26, sgop_expt_addr & 0x0000FFFF, - 0xBF27, sgop_expt_addr >> 16, - 0xBF28, sgop_peak_addr & 0x0000FFFF, - 0xBF29, sgop_peak_addr >> 16, - 0xBF2A, vbv_alert_addr & 0x0000FFFF, - 0xBF2B, vbv_alert_addr >> 16, - 0xBF2C, 0, - 0xBF2D, 0, - 0, 0, - - 0x200e, 0x0000, - 0xBF2E, vbv_alert_addr & 0x0000FFFF, - 0xBF2F, vbv_alert_addr >> 16, - 0xBF30, cplx[0] & 0x0000FFFF, - 0xBF31, cplx[0] >> 16, - 0xBF32, cplx[1] & 0x0000FFFF, - 0xBF33, cplx[1] >> 16, - 0xBF34, cplx[2] & 0x0000FFFF, - 0xBF35, cplx[2] >> 16, - 0xBF36, cplx[3] & 0x0000FFFF, - 0xBF37, cplx[3] >> 16, - 0xBF38, 0, - 0xBF39, 0, - 0xBF3A, total_expt_addr & 0x0000FFFF, - 0xBF3B, total_expt_addr >> 16, - 0, 0, - - 0x200e, 0x0000, - 0xBF3C, total_expt_addr & 0x0000FFFF, - 0xBF3D, total_expt_addr >> 16, - 0xBF3E, 0, - 0xBF3F, 0, - 0xBF48, 0, - 0xBF49, 0, - 0xBF4A, calc_q < 4 ? 4 : (calc_q > 124 ? 124 : calc_q), - 0xBF4B, 4, - 0xBF4C, 0, - 0xBF4D, 0, - 0xBF4E, 0, - 0xBF4F, 0, - 0xBF50, 0, - 0xBF51, 0, - 0, 0, - - 0x200e, 0x0000, - 0xBF40, sgop_expt_addr & 0x0000FFFF, - 0xBF41, sgop_expt_addr >> 16, - 0xBF42, 0, - 0xBF43, 0, - 0xBF44, 0, - 0xBF45, 0, - 0xBF46, (go->width >> 4) * (go->height >> 4), - 0xBF47, 0, - 0xBF64, 0, - 0xBF65, 0, - 0xBF18, framelen[4], - 0xBF19, framelen[5], - 0xBF1A, framelen[6], - 0xBF1B, framelen[7], - 0, 0, - -#if 0 - /* Remove once we don't care about matching */ - 0x200e, 0x0000, - 0xBF56, 4, - 0xBF57, 0, - 0xBF58, 5, - 0xBF59, 0, - 0xBF5A, 6, - 0xBF5B, 0, - 0xBF5C, 8, - 0xBF5D, 0, - 0xBF5E, 1, - 0xBF5F, 0, - 0xBF60, 1, - 0xBF61, 0, - 0xBF62, 0, - 0xBF63, 0, - 0, 0, -#else - 0x2008, 0x0000, - 0xBF56, 4, - 0xBF57, 0, - 0xBF58, 5, - 0xBF59, 0, - 0xBF5A, 6, - 0xBF5B, 0, - 0xBF5C, 8, - 0xBF5D, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, -#endif - - 0x200e, 0x0000, - 0xBF10, 0, - 0xBF11, 0, - 0xBF12, 0, - 0xBF13, 0, - 0xBF14, 0, - 0xBF15, 0, - 0xBF16, 0, - 0xBF17, 0, - 0xBF7E, 0, - 0xBF7F, 1, - 0xBF52, framelen[0], - 0xBF53, framelen[1], - 0xBF54, framelen[2], - 0xBF55, framelen[3], - 0, 0, - }; - - return copy_packages(code, pack, 6, space); -} - -static int config_package(struct go7007 *go, __le16 *code, int space) -{ - int fps = go->sensor_framerate / go->fps_scale / 1000; - int rows = go->interlace_coding ? go->height / 32 : go->height / 16; - int brc_window_size = fps; - int q_min = 2, q_max = 31; - int THACCoeffSet0 = 0; - u16 pack[] = { - 0x200e, 0x0000, - 0xc002, 0x14b4, - 0xc003, 0x28b4, - 0xc004, 0x3c5a, - 0xdc05, 0x2a77, - 0xc6c3, go->format == V4L2_PIX_FMT_MPEG4 ? 0 : - (go->format == V4L2_PIX_FMT_H263 ? 0 : 1), - 0xc680, go->format == V4L2_PIX_FMT_MPEG4 ? 0xf1 : - (go->format == V4L2_PIX_FMT_H263 ? 0x61 : - 0xd3), - 0xc780, 0x0140, - 0xe009, 0x0001, - 0xc60f, 0x0008, - 0xd4ff, 0x0002, - 0xe403, 2340, - 0xe406, 75, - 0xd411, 0x0001, - 0xd410, 0xa1d6, - 0x0001, 0x2801, - - 0x200d, 0x0000, - 0xe402, 0x018b, - 0xe401, 0x8b01, - 0xd472, (go->board_info->sensor_flags & - GO7007_SENSOR_TV) && - (!go->interlace_coding) ? - 0x01b0 : 0x0170, - 0xd475, (go->board_info->sensor_flags & - GO7007_SENSOR_TV) && - (!go->interlace_coding) ? - 0x0008 : 0x0009, - 0xc404, go->interlace_coding ? 0x44 : - (go->format == V4L2_PIX_FMT_MPEG4 ? 0x11 : - (go->format == V4L2_PIX_FMT_MPEG1 ? 0x02 : - (go->format == V4L2_PIX_FMT_MPEG2 ? 0x04 : - (go->format == V4L2_PIX_FMT_H263 ? 0x08 : - 0x20)))), - 0xbf0a, (go->format == V4L2_PIX_FMT_MPEG4 ? 8 : - (go->format == V4L2_PIX_FMT_MPEG1 ? 1 : - (go->format == V4L2_PIX_FMT_MPEG2 ? 2 : - (go->format == V4L2_PIX_FMT_H263 ? 4 : 16)))) | - ((go->repeat_seqhead ? 1 : 0) << 6) | - ((go->dvd_mode ? 1 : 0) << 9) | - ((go->gop_header_enable ? 1 : 0) << 10), - 0xbf0b, 0, - 0xdd5a, go->ipb ? 0x14 : 0x0a, - 0xbf0c, 0, - 0xbf0d, 0, - 0xc683, THACCoeffSet0, - 0xc40a, (go->width << 4) | rows, - 0xe01a, go->board_info->hpi_buffer_cap, - 0, 0, - 0, 0, - - 0x2008, 0, - 0xe402, 0x88, - 0xe401, 0x8f01, - 0xbf6a, 0, - 0xbf6b, 0, - 0xbf6c, 0, - 0xbf6d, 0, - 0xbf6e, 0, - 0xbf6f, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - - 0x200e, 0, - 0xbf66, brc_window_size, - 0xbf67, 0, - 0xbf68, q_min, - 0xbf69, q_max, - 0xbfe0, 0, - 0xbfe1, 0, - 0xbfe2, 0, - 0xbfe3, go->ipb ? 3 : 1, - 0xc031, go->board_info->sensor_flags & - GO7007_SENSOR_VBI ? 1 : 0, - 0xc01c, 0x1f, - 0xdd8c, 0x15, - 0xdd94, 0x15, - 0xdd88, go->ipb ? 0x1401 : 0x0a01, - 0xdd90, go->ipb ? 0x1401 : 0x0a01, - 0, 0, - - 0x200e, 0, - 0xbfe4, 0, - 0xbfe5, 0, - 0xbfe6, 0, - 0xbfe7, fps << 8, - 0xbfe8, 0x3a00, - 0xbfe9, 0, - 0xbfea, 0, - 0xbfeb, 0, - 0xbfec, (go->interlace_coding ? 1 << 15 : 0) | - (go->modet_enable ? 0xa : 0) | - (go->board_info->sensor_flags & - GO7007_SENSOR_VBI ? 1 : 0), - 0xbfed, 0, - 0xbfee, 0, - 0xbfef, 0, - 0xbff0, go->board_info->sensor_flags & - GO7007_SENSOR_TV ? 0xf060 : 0xb060, - 0xbff1, 0, - 0, 0, - }; - - return copy_packages(code, pack, 5, space); -} - -static int seqhead_to_package(struct go7007 *go, __le16 *code, int space, - int (*sequence_header_func)(struct go7007 *go, - unsigned char *buf, int ext)) -{ - int vop_time_increment_bitlength = vti_bitlen(go); - int fps = go->sensor_framerate / go->fps_scale * - (go->interlace_coding ? 2 : 1); - unsigned char buf[40] = { }; - int len = sequence_header_func(go, buf, 1); - u16 pack[] = { - 0x2006, 0, - 0xbf08, fps, - 0xbf09, 0, - 0xbff2, vop_time_increment_bitlength, - 0xbff3, (1 << vop_time_increment_bitlength) - 1, - 0xbfe6, 0, - 0xbfe7, (fps / 1000) << 8, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - - 0x2007, 0, - 0xc800, buf[2] << 8 | buf[3], - 0xc801, buf[4] << 8 | buf[5], - 0xc802, buf[6] << 8 | buf[7], - 0xc803, buf[8] << 8 | buf[9], - 0xc406, 64, - 0xc407, len - 64, - 0xc61b, 1, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - - 0x200e, 0, - 0xc808, buf[10] << 8 | buf[11], - 0xc809, buf[12] << 8 | buf[13], - 0xc80a, buf[14] << 8 | buf[15], - 0xc80b, buf[16] << 8 | buf[17], - 0xc80c, buf[18] << 8 | buf[19], - 0xc80d, buf[20] << 8 | buf[21], - 0xc80e, buf[22] << 8 | buf[23], - 0xc80f, buf[24] << 8 | buf[25], - 0xc810, buf[26] << 8 | buf[27], - 0xc811, buf[28] << 8 | buf[29], - 0xc812, buf[30] << 8 | buf[31], - 0xc813, buf[32] << 8 | buf[33], - 0xc814, buf[34] << 8 | buf[35], - 0xc815, buf[36] << 8 | buf[37], - 0, 0, - 0, 0, - 0, 0, - }; - - return copy_packages(code, pack, 3, space); -} - -static int relative_prime(int big, int little) -{ - int remainder; - - while (little != 0) { - remainder = big % little; - big = little; - little = remainder; - } - return big; -} - -static int avsync_to_package(struct go7007 *go, __le16 *code, int space) -{ - int arate = go->board_info->audio_rate * 1001 * go->fps_scale; - int ratio = arate / go->sensor_framerate; - int adjratio = ratio * 215 / 100; - int rprime = relative_prime(go->sensor_framerate, - arate % go->sensor_framerate); - int f1 = (arate % go->sensor_framerate) / rprime; - int f2 = (go->sensor_framerate - arate % go->sensor_framerate) / rprime; - u16 pack[] = { - 0x200e, 0, - 0xbf98, (u16)((-adjratio) & 0xffff), - 0xbf99, (u16)((-adjratio) >> 16), - 0xbf92, 0, - 0xbf93, 0, - 0xbff4, f1 > f2 ? f1 : f2, - 0xbff5, f1 < f2 ? f1 : f2, - 0xbff6, f1 < f2 ? ratio : ratio + 1, - 0xbff7, f1 > f2 ? ratio : ratio + 1, - 0xbff8, 0, - 0xbff9, 0, - 0xbffa, adjratio & 0xffff, - 0xbffb, adjratio >> 16, - 0xbf94, 0, - 0xbf95, 0, - 0, 0, - }; - - return copy_packages(code, pack, 1, space); -} - -static int final_package(struct go7007 *go, __le16 *code, int space) -{ - int rows = go->interlace_coding ? go->height / 32 : go->height / 16; - u16 pack[] = { - 0x8000, - 0, - 0, - 0, - 0, - 0, - 0, - 2, - ((go->board_info->sensor_flags & GO7007_SENSOR_TV) && - (!go->interlace_coding) ? - (1 << 14) | (1 << 9) : 0) | - ((go->encoder_subsample ? 1 : 0) << 8) | - (go->board_info->sensor_flags & - GO7007_SENSOR_CONFIG_MASK), - ((go->encoder_v_halve ? 1 : 0) << 14) | - (go->encoder_v_halve ? rows << 9 : rows << 8) | - (go->encoder_h_halve ? 1 << 6 : 0) | - (go->encoder_h_halve ? go->width >> 3 : go->width >> 4), - (1 << 15) | (go->encoder_v_offset << 6) | - (1 << 7) | (go->encoder_h_offset >> 2), - (1 << 6), - 0, - 0, - ((go->fps_scale - 1) << 8) | - (go->board_info->sensor_flags & GO7007_SENSOR_TV ? - (1 << 7) : 0) | - 0x41, - go->ipb ? 0xd4c : 0x36b, - (rows << 8) | (go->width >> 4), - go->format == V4L2_PIX_FMT_MPEG4 ? 0x0404 : 0, - (1 << 15) | ((go->interlace_coding ? 1 : 0) << 13) | - ((go->closed_gop ? 1 : 0) << 12) | - ((go->format == V4L2_PIX_FMT_MPEG4 ? 1 : 0) << 11) | - /* (1 << 9) | */ - ((go->ipb ? 3 : 0) << 7) | - ((go->modet_enable ? 1 : 0) << 2) | - ((go->dvd_mode ? 1 : 0) << 1) | 1, - (go->format == V4L2_PIX_FMT_MPEG1 ? 0x89a0 : - (go->format == V4L2_PIX_FMT_MPEG2 ? 0x89a0 : - (go->format == V4L2_PIX_FMT_MJPEG ? 0x89a0 : - (go->format == V4L2_PIX_FMT_MPEG4 ? 0x8920 : - (go->format == V4L2_PIX_FMT_H263 ? 0x8920 : 0))))), - go->ipb ? 0x1f15 : 0x1f0b, - go->ipb ? 0x0015 : 0x000b, - go->ipb ? 0xa800 : 0x5800, - 0xffff, - 0x0020 + 0x034b * 0, - 0x0020 + 0x034b * 1, - 0x0020 + 0x034b * 2, - 0x0020 + 0x034b * 3, - 0x0020 + 0x034b * 4, - 0x0020 + 0x034b * 5, - go->ipb ? (go->gop_size / 3) : go->gop_size, - (go->height >> 4) * (go->width >> 4) * 110 / 100, - }; - - return copy_packages(code, pack, 1, space); -} - -static int audio_to_package(struct go7007 *go, __le16 *code, int space) -{ - int clock_config = ((go->board_info->audio_flags & - GO7007_AUDIO_I2S_MASTER ? 1 : 0) << 11) | - ((go->board_info->audio_flags & - GO7007_AUDIO_OKI_MODE ? 1 : 0) << 8) | - (((go->board_info->audio_bclk_div / 4) - 1) << 4) | - (go->board_info->audio_main_div - 1); - u16 pack[] = { - 0x200d, 0, - 0x9002, 0, - 0x9002, 0, - 0x9031, 0, - 0x9032, 0, - 0x9033, 0, - 0x9034, 0, - 0x9035, 0, - 0x9036, 0, - 0x9037, 0, - 0x9040, 0, - 0x9000, clock_config, - 0x9001, (go->board_info->audio_flags & 0xffff) | - (1 << 9), - 0x9000, ((go->board_info->audio_flags & - GO7007_AUDIO_I2S_MASTER ? - 1 : 0) << 10) | - clock_config, - 0, 0, - 0, 0, - 0x2005, 0, - 0x9041, 0, - 0x9042, 256, - 0x9043, 0, - 0x9044, 16, - 0x9045, 16, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - }; - - return copy_packages(code, pack, 2, space); -} - -static int modet_to_package(struct go7007 *go, __le16 *code, int space) -{ - int ret, mb, i, addr, cnt = 0; - u16 pack[32]; - u16 thresholds[] = { - 0x200e, 0, - 0xbf82, go->modet[0].pixel_threshold, - 0xbf83, go->modet[1].pixel_threshold, - 0xbf84, go->modet[2].pixel_threshold, - 0xbf85, go->modet[3].pixel_threshold, - 0xbf86, go->modet[0].motion_threshold, - 0xbf87, go->modet[1].motion_threshold, - 0xbf88, go->modet[2].motion_threshold, - 0xbf89, go->modet[3].motion_threshold, - 0xbf8a, go->modet[0].mb_threshold, - 0xbf8b, go->modet[1].mb_threshold, - 0xbf8c, go->modet[2].mb_threshold, - 0xbf8d, go->modet[3].mb_threshold, - 0xbf8e, 0, - 0xbf8f, 0, - 0, 0, - }; - - ret = copy_packages(code, thresholds, 1, space); - if (ret < 0) - return -1; - cnt += ret; - - addr = 0xbac0; - memset(pack, 0, 64); - i = 0; - for (mb = 0; mb < 1624; ++mb) { - pack[i * 2 + 3] <<= 2; - pack[i * 2 + 3] |= go->modet_map[mb]; - if (mb % 8 != 7) - continue; - pack[i * 2 + 2] = addr++; - ++i; - if (i == 10 || mb == 1623) { - pack[0] = 0x2000 | i; - ret = copy_packages(code + cnt, pack, 1, space - cnt); - if (ret < 0) - return -1; - cnt += ret; - i = 0; - memset(pack, 0, 64); - } - pack[i * 2 + 3] = 0; - } - - memset(pack, 0, 64); - i = 0; - for (addr = 0xbb90; addr < 0xbbfa; ++addr) { - pack[i * 2 + 2] = addr; - pack[i * 2 + 3] = 0; - ++i; - if (i == 10 || addr == 0xbbf9) { - pack[0] = 0x2000 | i; - ret = copy_packages(code + cnt, pack, 1, space - cnt); - if (ret < 0) - return -1; - cnt += ret; - i = 0; - memset(pack, 0, 64); - } - } - return cnt; -} - -static int do_special(struct go7007 *go, u16 type, __le16 *code, int space, - int *framelen) -{ - switch (type) { - case SPECIAL_FRM_HEAD: - switch (go->format) { - case V4L2_PIX_FMT_MJPEG: - return gen_mjpeghdr_to_package(go, code, space); - case V4L2_PIX_FMT_MPEG1: - case V4L2_PIX_FMT_MPEG2: - return gen_mpeg1hdr_to_package(go, code, space, - framelen); - case V4L2_PIX_FMT_MPEG4: - return gen_mpeg4hdr_to_package(go, code, space, - framelen); - } - case SPECIAL_BRC_CTRL: - return brctrl_to_package(go, code, space, framelen); - case SPECIAL_CONFIG: - return config_package(go, code, space); - case SPECIAL_SEQHEAD: - switch (go->format) { - case V4L2_PIX_FMT_MPEG1: - case V4L2_PIX_FMT_MPEG2: - return seqhead_to_package(go, code, space, - mpeg1_sequence_header); - case V4L2_PIX_FMT_MPEG4: - return seqhead_to_package(go, code, space, - mpeg4_sequence_header); - default: - return 0; - } - case SPECIAL_AV_SYNC: - return avsync_to_package(go, code, space); - case SPECIAL_FINAL: - return final_package(go, code, space); - case SPECIAL_AUDIO: - return audio_to_package(go, code, space); - case SPECIAL_MODET: - return modet_to_package(go, code, space); - } - dev_err(go->dev, - "firmware file contains unsupported feature %04x\n", type); - return -1; -} - -int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen) -{ - const struct firmware *fw_entry; - __le16 *code, *src; - int framelen[8] = { }; /* holds the lengths of empty frame templates */ - int codespace = 64 * 1024, i = 0, srclen, chunk_len, chunk_flags; - int mode_flag; - int ret; - - switch (go->format) { - case V4L2_PIX_FMT_MJPEG: - mode_flag = FLAG_MODE_MJPEG; - break; - case V4L2_PIX_FMT_MPEG1: - mode_flag = FLAG_MODE_MPEG1; - break; - case V4L2_PIX_FMT_MPEG2: - mode_flag = FLAG_MODE_MPEG2; - break; - case V4L2_PIX_FMT_MPEG4: - mode_flag = FLAG_MODE_MPEG4; - break; - default: - return -1; - } - if (request_firmware(&fw_entry, GO7007_FW_NAME, go->dev)) { - dev_err(go->dev, - "unable to load firmware from file \"%s\"\n", - GO7007_FW_NAME); - return -1; - } - code = kzalloc(codespace * 2, GFP_KERNEL); - if (code == NULL) - goto fw_failed; - - src = (__le16 *)fw_entry->data; - srclen = fw_entry->size / 2; - while (srclen >= 2) { - chunk_flags = __le16_to_cpu(src[0]); - chunk_len = __le16_to_cpu(src[1]); - if (chunk_len + 2 > srclen) { - dev_err(go->dev, - "firmware file \"%s\" appears to be corrupted\n", - GO7007_FW_NAME); - goto fw_failed; - } - if (chunk_flags & mode_flag) { - if (chunk_flags & FLAG_SPECIAL) { - ret = do_special(go, __le16_to_cpu(src[2]), - &code[i], codespace - i, framelen); - if (ret < 0) { - dev_err(go->dev, - "insufficient memory for firmware construction\n"); - goto fw_failed; - } - i += ret; - } else { - if (codespace - i < chunk_len) { - dev_err(go->dev, - "insufficient memory for firmware construction\n"); - goto fw_failed; - } - memcpy(&code[i], &src[2], chunk_len * 2); - i += chunk_len; - } - } - srclen -= chunk_len + 2; - src += chunk_len + 2; - } - release_firmware(fw_entry); - *fw = (u8 *)code; - *fwlen = i * 2; - return 0; - -fw_failed: - kfree(code); - release_firmware(fw_entry); - return -1; -} - -MODULE_FIRMWARE(GO7007_FW_NAME); diff --git a/drivers/staging/media/go7007/go7007-i2c.c b/drivers/staging/media/go7007/go7007-i2c.c deleted file mode 100644 index 4cf4c0d65085..000000000000 --- a/drivers/staging/media/go7007/go7007-i2c.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2005-2006 Micronas USA Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * 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/delay.h> -#include <linux/sched.h> -#include <linux/list.h> -#include <linux/unistd.h> -#include <linux/time.h> -#include <linux/device.h> -#include <linux/i2c.h> -#include <linux/mutex.h> -#include <linux/uaccess.h> - -#include "go7007-priv.h" - -/********************* Driver for on-board I2C adapter *********************/ - -/* #define GO7007_I2C_DEBUG */ - -#define SPI_I2C_ADDR_BASE 0x1400 -#define STATUS_REG_ADDR (SPI_I2C_ADDR_BASE + 0x2) -#define I2C_CTRL_REG_ADDR (SPI_I2C_ADDR_BASE + 0x6) -#define I2C_DEV_UP_ADDR_REG_ADDR (SPI_I2C_ADDR_BASE + 0x7) -#define I2C_LO_ADDR_REG_ADDR (SPI_I2C_ADDR_BASE + 0x8) -#define I2C_DATA_REG_ADDR (SPI_I2C_ADDR_BASE + 0x9) -#define I2C_CLKFREQ_REG_ADDR (SPI_I2C_ADDR_BASE + 0xa) - -#define I2C_STATE_MASK 0x0007 -#define I2C_READ_READY_MASK 0x0008 - -/* There is only one I2C port on the TW2804 that feeds all four GO7007 VIPs - * on the Adlink PCI-MPG24, so access is shared between all of them. */ -static DEFINE_MUTEX(adlink_mpg24_i2c_lock); - -static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read, - u16 command, int flags, u8 *data) -{ - int i, ret = -EIO; - u16 val; - - if (go->status == STATUS_SHUTDOWN) - return -ENODEV; - -#ifdef GO7007_I2C_DEBUG - if (read) - dev_dbg(go->dev, "go7007-i2c: reading 0x%02x on 0x%02x\n", - command, addr); - else - dev_dbg(go->dev, - "go7007-i2c: writing 0x%02x to 0x%02x on 0x%02x\n", - *data, command, addr); -#endif - - mutex_lock(&go->hw_lock); - - if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { - /* Bridge the I2C port on this GO7007 to the shared bus */ - mutex_lock(&adlink_mpg24_i2c_lock); - go7007_write_addr(go, 0x3c82, 0x0020); - } - - /* Wait for I2C adapter to be ready */ - for (i = 0; i < 10; ++i) { - if (go7007_read_addr(go, STATUS_REG_ADDR, &val) < 0) - goto i2c_done; - if (!(val & I2C_STATE_MASK)) - break; - msleep(100); - } - if (i == 10) { - dev_err(go->dev, "go7007-i2c: I2C adapter is hung\n"); - goto i2c_done; - } - - /* Set target register (command) */ - go7007_write_addr(go, I2C_CTRL_REG_ADDR, flags); - go7007_write_addr(go, I2C_LO_ADDR_REG_ADDR, command); - - /* If we're writing, send the data and target address and we're done */ - if (!read) { - go7007_write_addr(go, I2C_DATA_REG_ADDR, *data); - go7007_write_addr(go, I2C_DEV_UP_ADDR_REG_ADDR, - (addr << 9) | (command >> 8)); - ret = 0; - goto i2c_done; - } - - /* Otherwise, we're reading. First clear i2c_rx_data_rdy. */ - if (go7007_read_addr(go, I2C_DATA_REG_ADDR, &val) < 0) - goto i2c_done; - - /* Send the target address plus read flag */ - go7007_write_addr(go, I2C_DEV_UP_ADDR_REG_ADDR, - (addr << 9) | 0x0100 | (command >> 8)); - - /* Wait for i2c_rx_data_rdy */ - for (i = 0; i < 10; ++i) { - if (go7007_read_addr(go, STATUS_REG_ADDR, &val) < 0) - goto i2c_done; - if (val & I2C_READ_READY_MASK) - break; - msleep(100); - } - if (i == 10) { - dev_err(go->dev, "go7007-i2c: I2C adapter is hung\n"); - goto i2c_done; - } - - /* Retrieve the read byte */ - if (go7007_read_addr(go, I2C_DATA_REG_ADDR, &val) < 0) - goto i2c_done; - *data = val; - ret = 0; - -i2c_done: - if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { - /* Isolate the I2C port on this GO7007 from the shared bus */ - go7007_write_addr(go, 0x3c82, 0x0000); - mutex_unlock(&adlink_mpg24_i2c_lock); - } - mutex_unlock(&go->hw_lock); - return ret; -} - -static int go7007_smbus_xfer(struct i2c_adapter *adapter, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data *data) -{ - struct go7007 *go = i2c_get_adapdata(adapter); - - if (size != I2C_SMBUS_BYTE_DATA) - return -EIO; - return go7007_i2c_xfer(go, addr, read_write == I2C_SMBUS_READ, command, - flags & I2C_CLIENT_SCCB ? 0x10 : 0x00, &data->byte); -} - -/* VERY LIMITED I2C master xfer function -- only needed because the - * SMBus functions only support 8-bit commands and the SAA7135 uses - * 16-bit commands. The I2C interface on the GO7007, as limited as - * it is, does support this mode. */ - -static int go7007_i2c_master_xfer(struct i2c_adapter *adapter, - struct i2c_msg msgs[], int num) -{ - struct go7007 *go = i2c_get_adapdata(adapter); - int i; - - for (i = 0; i < num; ++i) { - /* We can only do two things here -- write three bytes, or - * write two bytes and read one byte. */ - if (msgs[i].len == 2) { - if (i + 1 == num || msgs[i].addr != msgs[i + 1].addr || - (msgs[i].flags & I2C_M_RD) || - !(msgs[i + 1].flags & I2C_M_RD) || - msgs[i + 1].len != 1) - return -EIO; - if (go7007_i2c_xfer(go, msgs[i].addr, 1, - (msgs[i].buf[0] << 8) | msgs[i].buf[1], - 0x01, &msgs[i + 1].buf[0]) < 0) - return -EIO; - ++i; - } else if (msgs[i].len == 3) { - if (msgs[i].flags & I2C_M_RD) - return -EIO; - if (msgs[i].len != 3) - return -EIO; - if (go7007_i2c_xfer(go, msgs[i].addr, 0, - (msgs[i].buf[0] << 8) | msgs[i].buf[1], - 0x01, &msgs[i].buf[2]) < 0) - return -EIO; - } else - return -EIO; - } - - return num; -} - -static u32 go7007_functionality(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_BYTE_DATA; -} - -static struct i2c_algorithm go7007_algo = { - .smbus_xfer = go7007_smbus_xfer, - .master_xfer = go7007_i2c_master_xfer, - .functionality = go7007_functionality, -}; - -static struct i2c_adapter go7007_adap_templ = { - .owner = THIS_MODULE, - .name = "WIS GO7007SB", - .algo = &go7007_algo, -}; - -int go7007_i2c_init(struct go7007 *go) -{ - memcpy(&go->i2c_adapter, &go7007_adap_templ, - sizeof(go7007_adap_templ)); - go->i2c_adapter.dev.parent = go->dev; - i2c_set_adapdata(&go->i2c_adapter, go); - if (i2c_add_adapter(&go->i2c_adapter) < 0) { - dev_err(go->dev, - "go7007-i2c: error: i2c_add_adapter failed\n"); - return -1; - } - return 0; -} diff --git a/drivers/staging/media/go7007/go7007-loader.c b/drivers/staging/media/go7007/go7007-loader.c deleted file mode 100644 index 491d0e697f5a..000000000000 --- a/drivers/staging/media/go7007/go7007-loader.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2008 Sensoray Company Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * 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/slab.h> -#include <linux/usb.h> -#include <linux/firmware.h> -#include <cypress_firmware.h> - -struct fw_config { - u16 vendor; - u16 product; - const char * const fw_name1; - const char * const fw_name2; -}; - -static struct fw_config fw_configs[] = { - { 0x1943, 0xa250, "go7007/s2250-1.fw", "go7007/s2250-2.fw" }, - { 0x093b, 0xa002, "go7007/px-m402u.fw", NULL }, - { 0x093b, 0xa004, "go7007/px-tv402u.fw", NULL }, - { 0x0eb1, 0x6666, "go7007/lr192.fw", NULL }, - { 0x0eb1, 0x6668, "go7007/wis-startrek.fw", NULL }, - { 0, 0, NULL, NULL } -}; -MODULE_FIRMWARE("go7007/s2250-1.fw"); -MODULE_FIRMWARE("go7007/s2250-2.fw"); -MODULE_FIRMWARE("go7007/px-m402u.fw"); -MODULE_FIRMWARE("go7007/px-tv402u.fw"); -MODULE_FIRMWARE("go7007/lr192.fw"); -MODULE_FIRMWARE("go7007/wis-startrek.fw"); - -static int go7007_loader_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *usbdev; - const struct firmware *fw; - u16 vendor, product; - const char *fw1, *fw2; - int ret; - int i; - - usbdev = usb_get_dev(interface_to_usbdev(interface)); - if (!usbdev) - goto failed2; - - if (usbdev->descriptor.bNumConfigurations != 1) { - dev_err(&interface->dev, "can't handle multiple config\n"); - goto failed2; - } - - vendor = le16_to_cpu(usbdev->descriptor.idVendor); - product = le16_to_cpu(usbdev->descriptor.idProduct); - - for (i = 0; fw_configs[i].fw_name1; i++) - if (fw_configs[i].vendor == vendor && - fw_configs[i].product == product) - break; - - /* Should never happen */ - if (fw_configs[i].fw_name1 == NULL) - goto failed2; - - fw1 = fw_configs[i].fw_name1; - fw2 = fw_configs[i].fw_name2; - - dev_info(&interface->dev, "loading firmware %s\n", fw1); - - if (request_firmware(&fw, fw1, &usbdev->dev)) { - dev_err(&interface->dev, - "unable to load firmware from file \"%s\"\n", fw1); - goto failed2; - } - ret = cypress_load_firmware(usbdev, fw, CYPRESS_FX2); - release_firmware(fw); - if (0 != ret) { - dev_err(&interface->dev, "loader download failed\n"); - goto failed2; - } - - if (fw2 == NULL) - return 0; - - if (request_firmware(&fw, fw2, &usbdev->dev)) { - dev_err(&interface->dev, - "unable to load firmware from file \"%s\"\n", fw2); - goto failed2; - } - ret = cypress_load_firmware(usbdev, fw, CYPRESS_FX2); - release_firmware(fw); - if (0 != ret) { - dev_err(&interface->dev, "firmware download failed\n"); - goto failed2; - } - return 0; - -failed2: - usb_put_dev(usbdev); - dev_err(&interface->dev, "probe failed\n"); - return -ENODEV; -} - -static void go7007_loader_disconnect(struct usb_interface *interface) -{ - dev_info(&interface->dev, "disconnect\n"); - usb_put_dev(interface_to_usbdev(interface)); - usb_set_intfdata(interface, NULL); -} - -static const struct usb_device_id go7007_loader_ids[] = { - { USB_DEVICE(0x1943, 0xa250) }, - { USB_DEVICE(0x093b, 0xa002) }, - { USB_DEVICE(0x093b, 0xa004) }, - { USB_DEVICE(0x0eb1, 0x6666) }, - { USB_DEVICE(0x0eb1, 0x6668) }, - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, go7007_loader_ids); - -static struct usb_driver go7007_loader_driver = { - .name = "go7007-loader", - .probe = go7007_loader_probe, - .disconnect = go7007_loader_disconnect, - .id_table = go7007_loader_ids, -}; - -module_usb_driver(go7007_loader_driver); - -MODULE_AUTHOR(""); -MODULE_DESCRIPTION("firmware loader for go7007-usb"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/media/go7007/go7007-priv.h b/drivers/staging/media/go7007/go7007-priv.h deleted file mode 100644 index 6e16af720504..000000000000 --- a/drivers/staging/media/go7007/go7007-priv.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (C) 2005-2006 Micronas USA Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * 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 is the private include file for the go7007 driver. It should not - * be included by anybody but the driver itself, and especially not by - * user-space applications. - */ - -#include <media/v4l2-device.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-fh.h> -#include <media/videobuf2-core.h> - -struct go7007; - -/* IDs to activate board-specific support code */ -#define GO7007_BOARDID_MATRIX_II 0 -#define GO7007_BOARDID_MATRIX_RELOAD 1 -#define GO7007_BOARDID_STAR_TREK 2 -#define GO7007_BOARDID_PCI_VOYAGER 3 -#define GO7007_BOARDID_XMEN 4 -#define GO7007_BOARDID_XMEN_II 5 -#define GO7007_BOARDID_XMEN_III 6 -#define GO7007_BOARDID_MATRIX_REV 7 -#define GO7007_BOARDID_PX_M402U 8 -#define GO7007_BOARDID_PX_TV402U 9 -#define GO7007_BOARDID_LIFEVIEW_LR192 10 /* TV Walker Ultra */ -#define GO7007_BOARDID_ENDURA 11 -#define GO7007_BOARDID_ADLINK_MPG24 12 -#define GO7007_BOARDID_SENSORAY_2250 13 /* Sensoray 2250/2251 */ -#define GO7007_BOARDID_ADS_USBAV_709 14 - -/* Various characteristics of each board */ -#define GO7007_BOARD_HAS_AUDIO (1<<0) -#define GO7007_BOARD_USE_ONBOARD_I2C (1<<1) -#define GO7007_BOARD_HAS_TUNER (1<<2) - -/* Characteristics of sensor devices */ -#define GO7007_SENSOR_VALID_POLAR (1<<0) -#define GO7007_SENSOR_HREF_POLAR (1<<1) -#define GO7007_SENSOR_VREF_POLAR (1<<2) -#define GO7007_SENSOR_FIELD_ID_POLAR (1<<3) -#define GO7007_SENSOR_BIT_WIDTH (1<<4) -#define GO7007_SENSOR_VALID_ENABLE (1<<5) -#define GO7007_SENSOR_656 (1<<6) -#define GO7007_SENSOR_CONFIG_MASK 0x7f -#define GO7007_SENSOR_TV (1<<7) -#define GO7007_SENSOR_VBI (1<<8) -#define GO7007_SENSOR_SCALING (1<<9) -#define GO7007_SENSOR_SAA7115 (1<<10) - -/* Characteristics of audio sensor devices */ -#define GO7007_AUDIO_I2S_MODE_1 (1) -#define GO7007_AUDIO_I2S_MODE_2 (2) -#define GO7007_AUDIO_I2S_MODE_3 (3) -#define GO7007_AUDIO_BCLK_POLAR (1<<2) -#define GO7007_AUDIO_WORD_14 (14<<4) -#define GO7007_AUDIO_WORD_16 (16<<4) -#define GO7007_AUDIO_ONE_CHANNEL (1<<11) -#define GO7007_AUDIO_I2S_MASTER (1<<16) -#define GO7007_AUDIO_OKI_MODE (1<<17) - -struct go7007_board_info { - unsigned int flags; - int hpi_buffer_cap; - unsigned int sensor_flags; - int sensor_width; - int sensor_height; - int sensor_framerate; - int sensor_h_offset; - int sensor_v_offset; - unsigned int audio_flags; - int audio_rate; - int audio_bclk_div; - int audio_main_div; - int num_i2c_devs; - struct go_i2c { - const char *type; - unsigned int is_video:1; - unsigned int is_audio:1; - int addr; - u32 flags; - } i2c_devs[5]; - int num_inputs; - struct { - int video_input; - int audio_index; - char *name; - } inputs[4]; - int video_config; - int num_aud_inputs; - struct { - int audio_input; - char *name; - } aud_inputs[3]; -}; - -struct go7007_hpi_ops { - int (*interface_reset)(struct go7007 *go); - int (*write_interrupt)(struct go7007 *go, int addr, int data); - int (*read_interrupt)(struct go7007 *go); - int (*stream_start)(struct go7007 *go); - int (*stream_stop)(struct go7007 *go); - int (*send_firmware)(struct go7007 *go, u8 *data, int len); - int (*send_command)(struct go7007 *go, unsigned int cmd, void *arg); - void (*release)(struct go7007 *go); -}; - -/* The video buffer size must be a multiple of PAGE_SIZE */ -#define GO7007_BUF_PAGES (128 * 1024 / PAGE_SIZE) -#define GO7007_BUF_SIZE (GO7007_BUF_PAGES << PAGE_SHIFT) - -struct go7007_buffer { - struct vb2_buffer vb; - struct list_head list; - unsigned int frame_offset; - u32 modet_active; -}; - -#define GO7007_RATIO_1_1 0 -#define GO7007_RATIO_4_3 1 -#define GO7007_RATIO_16_9 2 - -enum go7007_parser_state { - STATE_DATA, - STATE_00, - STATE_00_00, - STATE_00_00_01, - STATE_FF, - STATE_VBI_LEN_A, - STATE_VBI_LEN_B, - STATE_MODET_MAP, - STATE_UNPARSED, -}; - -struct go7007 { - struct device *dev; - u8 bus_info[32]; - const struct go7007_board_info *board_info; - unsigned int board_id; - int tuner_type; - int channel_number; /* for multi-channel boards like Adlink PCI-MPG24 */ - char name[64]; - struct video_device vdev; - void *boot_fw; - unsigned boot_fw_len; - struct v4l2_device v4l2_dev; - struct v4l2_ctrl_handler hdl; - struct v4l2_ctrl *mpeg_video_encoding; - struct v4l2_ctrl *mpeg_video_gop_size; - struct v4l2_ctrl *mpeg_video_gop_closure; - struct v4l2_ctrl *mpeg_video_bitrate; - struct v4l2_ctrl *mpeg_video_aspect_ratio; - struct v4l2_ctrl *mpeg_video_b_frames; - struct v4l2_ctrl *mpeg_video_rep_seqheader; - enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status; - spinlock_t spinlock; - struct mutex hw_lock; - struct mutex serialize_lock; - int audio_enabled; - struct v4l2_subdev *sd_video; - struct v4l2_subdev *sd_audio; - u8 usb_buf[16]; - - /* Video input */ - int input; - int aud_input; - enum { GO7007_STD_NTSC, GO7007_STD_PAL, GO7007_STD_OTHER } standard; - v4l2_std_id std; - int sensor_framerate; - int width; - int height; - int encoder_h_offset; - int encoder_v_offset; - unsigned int encoder_h_halve:1; - unsigned int encoder_v_halve:1; - unsigned int encoder_subsample:1; - - /* Encoder config */ - u32 format; - int bitrate; - int fps_scale; - int pali; - int aspect_ratio; - int gop_size; - unsigned int ipb:1; - unsigned int closed_gop:1; - unsigned int repeat_seqhead:1; - unsigned int seq_header_enable:1; - unsigned int gop_header_enable:1; - unsigned int dvd_mode:1; - unsigned int interlace_coding:1; - - /* Motion detection */ - unsigned int modet_enable:1; - struct { - unsigned int enable:1; - int pixel_threshold; - int motion_threshold; - int mb_threshold; - } modet[4]; - unsigned char modet_map[1624]; - unsigned char active_map[216]; - - /* Video streaming */ - struct mutex queue_lock; - struct vb2_queue vidq; - enum go7007_parser_state state; - int parse_length; - u16 modet_word; - int seen_frame; - u32 next_seq; - struct list_head vidq_active; - wait_queue_head_t frame_waitq; - struct go7007_buffer *active_buf; - - /* Audio streaming */ - void (*audio_deliver)(struct go7007 *go, u8 *buf, int length); - void *snd_context; - - /* I2C */ - int i2c_adapter_online; - struct i2c_adapter i2c_adapter; - - /* HPI driver */ - struct go7007_hpi_ops *hpi_ops; - void *hpi_context; - int interrupt_available; - wait_queue_head_t interrupt_waitq; - unsigned short interrupt_value; - unsigned short interrupt_data; -}; - -static inline struct go7007 *to_go7007(struct v4l2_device *v4l2_dev) -{ - return container_of(v4l2_dev, struct go7007, v4l2_dev); -} - -/* All of these must be called with the hpi_lock mutex held! */ -#define go7007_interface_reset(go) \ - ((go)->hpi_ops->interface_reset(go)) -#define go7007_write_interrupt(go, x, y) \ - ((go)->hpi_ops->write_interrupt)((go), (x), (y)) -#define go7007_stream_start(go) \ - ((go)->hpi_ops->stream_start(go)) -#define go7007_stream_stop(go) \ - ((go)->hpi_ops->stream_stop(go)) -#define go7007_send_firmware(go, x, y) \ - ((go)->hpi_ops->send_firmware)((go), (x), (y)) -#define go7007_write_addr(go, x, y) \ - ((go)->hpi_ops->write_interrupt)((go), (x)|0x8000, (y)) - -/* go7007-driver.c */ -int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data); -int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data); -int go7007_boot_encoder(struct go7007 *go, int init_i2c); -int go7007_reset_encoder(struct go7007 *go); -int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs); -int go7007_start_encoder(struct go7007 *go); -void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length); -struct go7007 *go7007_alloc(const struct go7007_board_info *board, - struct device *dev); -void go7007_update_board(struct go7007 *go); - -/* go7007-fw.c */ -int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen); - -/* go7007-i2c.c */ -int go7007_i2c_init(struct go7007 *go); -int go7007_i2c_remove(struct go7007 *go); - -/* go7007-v4l2.c */ -int go7007_v4l2_init(struct go7007 *go); -int go7007_v4l2_ctrl_init(struct go7007 *go); -void go7007_v4l2_remove(struct go7007 *go); - -/* snd-go7007.c */ -int go7007_snd_init(struct go7007 *go); -int go7007_snd_remove(struct go7007 *go); diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c deleted file mode 100644 index 2f62be905cd1..000000000000 --- a/drivers/staging/media/go7007/go7007-usb.c +++ /dev/null @@ -1,1349 +0,0 @@ -/* - * Copyright (C) 2005-2006 Micronas USA Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/wait.h> -#include <linux/list.h> -#include <linux/slab.h> -#include <linux/time.h> -#include <linux/mm.h> -#include <linux/usb.h> -#include <linux/i2c.h> -#include <asm/byteorder.h> -#include <media/saa7115.h> -#include <media/tuner.h> -#include <media/uda1342.h> - -#include "go7007-priv.h" - -static unsigned int assume_endura; -module_param(assume_endura, int, 0644); -MODULE_PARM_DESC(assume_endura, - "when probing fails, hardware is a Pelco Endura"); - -/* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */ - -#define HPI_STATUS_ADDR 0xFFF4 -#define INT_PARAM_ADDR 0xFFF6 -#define INT_INDEX_ADDR 0xFFF8 - -/* - * Pipes on EZ-USB interface: - * 0 snd - Control - * 0 rcv - Control - * 2 snd - Download firmware (control) - * 4 rcv - Read Interrupt (interrupt) - * 6 rcv - Read Video (bulk) - * 8 rcv - Read Audio (bulk) - */ - -#define GO7007_USB_EZUSB (1<<0) -#define GO7007_USB_EZUSB_I2C (1<<1) - -struct go7007_usb_board { - unsigned int flags; - struct go7007_board_info main_info; -}; - -struct go7007_usb { - const struct go7007_usb_board *board; - struct mutex i2c_lock; - struct usb_device *usbdev; - struct urb *video_urbs[8]; - struct urb *audio_urbs[8]; - struct urb *intr_urb; -}; - -/*********************** Product specification data ***********************/ - -static const struct go7007_usb_board board_matrix_ii = { - .flags = GO7007_USB_EZUSB, - .main_info = { - .flags = GO7007_BOARD_HAS_AUDIO | - GO7007_BOARD_USE_ONBOARD_I2C, - .audio_flags = GO7007_AUDIO_I2S_MODE_1 | - GO7007_AUDIO_WORD_16, - .audio_rate = 48000, - .audio_bclk_div = 8, - .audio_main_div = 2, - .hpi_buffer_cap = 7, - .sensor_flags = GO7007_SENSOR_656 | - GO7007_SENSOR_VALID_ENABLE | - GO7007_SENSOR_TV | - GO7007_SENSOR_SAA7115 | - GO7007_SENSOR_VBI | - GO7007_SENSOR_SCALING, - .num_i2c_devs = 1, - .i2c_devs = { - { - .type = "saa7115", - .addr = 0x20, - .is_video = 1, - }, - }, - .num_inputs = 2, - .inputs = { - { - .video_input = 0, - .name = "Composite", - }, - { - .video_input = 9, - .name = "S-Video", - }, - }, - .video_config = SAA7115_IDQ_IS_DEFAULT, - }, -}; - -static const struct go7007_usb_board board_matrix_reload = { - .flags = GO7007_USB_EZUSB, - .main_info = { - .flags = GO7007_BOARD_HAS_AUDIO | - GO7007_BOARD_USE_ONBOARD_I2C, - .audio_flags = GO7007_AUDIO_I2S_MODE_1 | - GO7007_AUDIO_I2S_MASTER | - GO7007_AUDIO_WORD_16, - .audio_rate = 48000, - .audio_bclk_div = 8, - .audio_main_div = 2, - .hpi_buffer_cap = 7, - .sensor_flags = GO7007_SENSOR_656 | - GO7007_SENSOR_TV, - .num_i2c_devs = 1, - .i2c_devs = { - { - .type = "saa7113", - .addr = 0x25, - .is_video = 1, - }, - }, - .num_inputs = 2, - .inputs = { - { - .video_input = 0, - .name = "Composite", - }, - { - .video_input = 9, - .name = "S-Video", - }, - }, - .video_config = SAA7115_IDQ_IS_DEFAULT, - }, -}; - -static const struct go7007_usb_board board_star_trek = { - .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, - .main_info = { - .flags = GO7007_BOARD_HAS_AUDIO, /* | - GO7007_BOARD_HAS_TUNER, */ - .sensor_flags = GO7007_SENSOR_656 | - GO7007_SENSOR_VALID_ENABLE | - GO7007_SENSOR_TV | - GO7007_SENSOR_SAA7115 | - GO7007_SENSOR_VBI | - GO7007_SENSOR_SCALING, - .audio_flags = GO7007_AUDIO_I2S_MODE_1 | - GO7007_AUDIO_WORD_16, - .audio_bclk_div = 8, - .audio_main_div = 2, - .hpi_buffer_cap = 7, - .num_i2c_devs = 1, - .i2c_devs = { - { - .type = "saa7115", - .addr = 0x20, - .is_video = 1, - }, - }, - .num_inputs = 2, - .inputs = { - /* { - * .video_input = 3, - * .audio_index = AUDIO_TUNER, - * .name = "Tuner", - * }, - */ - { - .video_input = 1, - /* .audio_index = AUDIO_EXTERN, */ - .name = "Composite", - }, - { - .video_input = 8, - /* .audio_index = AUDIO_EXTERN, */ - .name = "S-Video", - }, - }, - .video_config = SAA7115_IDQ_IS_DEFAULT, - }, -}; - -static const struct go7007_usb_board board_px_tv402u = { - .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, - .main_info = { - .flags = GO7007_BOARD_HAS_AUDIO | - GO7007_BOARD_HAS_TUNER, - .sensor_flags = GO7007_SENSOR_656 | - GO7007_SENSOR_VALID_ENABLE | - GO7007_SENSOR_TV | - GO7007_SENSOR_SAA7115 | - GO7007_SENSOR_VBI | - GO7007_SENSOR_SCALING, - .audio_flags = GO7007_AUDIO_I2S_MODE_1 | - GO7007_AUDIO_WORD_16, - .audio_bclk_div = 8, - .audio_main_div = 2, - .hpi_buffer_cap = 7, - .num_i2c_devs = 5, - .i2c_devs = { - { - .type = "saa7115", - .addr = 0x20, - .is_video = 1, - }, - { - .type = "uda1342", - .addr = 0x1a, - .is_audio = 1, - }, - { - .type = "tuner", - .addr = 0x60, - }, - { - .type = "tuner", - .addr = 0x43, - }, - { - .type = "sony-btf-mpx", - .addr = 0x44, - }, - }, - .num_inputs = 3, - .inputs = { - { - .video_input = 3, - .audio_index = 0, - .name = "Tuner", - }, - { - .video_input = 1, - .audio_index = 1, - .name = "Composite", - }, - { - .video_input = 8, - .audio_index = 1, - .name = "S-Video", - }, - }, - .video_config = SAA7115_IDQ_IS_DEFAULT, - .num_aud_inputs = 2, - .aud_inputs = { - { - .audio_input = UDA1342_IN2, - .name = "Tuner", - }, - { - .audio_input = UDA1342_IN1, - .name = "Line In", - }, - }, - }, -}; - -static const struct go7007_usb_board board_xmen = { - .flags = 0, - .main_info = { - .flags = GO7007_BOARD_USE_ONBOARD_I2C, - .hpi_buffer_cap = 0, - .sensor_flags = GO7007_SENSOR_VREF_POLAR, - .sensor_width = 320, - .sensor_height = 240, - .sensor_framerate = 30030, - .audio_flags = GO7007_AUDIO_ONE_CHANNEL | - GO7007_AUDIO_I2S_MODE_3 | - GO7007_AUDIO_WORD_14 | - GO7007_AUDIO_I2S_MASTER | - GO7007_AUDIO_BCLK_POLAR | - GO7007_AUDIO_OKI_MODE, - .audio_rate = 8000, - .audio_bclk_div = 48, - .audio_main_div = 1, - .num_i2c_devs = 1, - .i2c_devs = { - { - .type = "ov7640", - .addr = 0x21, - }, - }, - .num_inputs = 1, - .inputs = { - { - .name = "Camera", - }, - }, - }, -}; - -static const struct go7007_usb_board board_matrix_revolution = { - .flags = GO7007_USB_EZUSB, - .main_info = { - .flags = GO7007_BOARD_HAS_AUDIO | - GO7007_BOARD_USE_ONBOARD_I2C, - .audio_flags = GO7007_AUDIO_I2S_MODE_1 | - GO7007_AUDIO_I2S_MASTER | - GO7007_AUDIO_WORD_16, - .audio_rate = 48000, - .audio_bclk_div = 8, - .audio_main_div = 2, - .hpi_buffer_cap = 7, - .sensor_flags = GO7007_SENSOR_656 | - GO7007_SENSOR_TV | - GO7007_SENSOR_VBI, - .num_i2c_devs = 1, - .i2c_devs = { - { - .type = "tw9903", - .is_video = 1, - .addr = 0x44, - }, - }, - .num_inputs = 2, - .inputs = { - { - .video_input = 2, - .name = "Composite", - }, - { - .video_input = 8, - .name = "S-Video", - }, - }, - }, -}; - -static const struct go7007_usb_board board_lifeview_lr192 = { - .flags = GO7007_USB_EZUSB, - .main_info = { - .flags = GO7007_BOARD_HAS_AUDIO | - GO7007_BOARD_USE_ONBOARD_I2C, - .audio_flags = GO7007_AUDIO_I2S_MODE_1 | - GO7007_AUDIO_WORD_16, - .audio_rate = 48000, - .audio_bclk_div = 8, - .audio_main_div = 2, - .hpi_buffer_cap = 7, - .sensor_flags = GO7007_SENSOR_656 | - GO7007_SENSOR_VALID_ENABLE | - GO7007_SENSOR_TV | - GO7007_SENSOR_VBI | - GO7007_SENSOR_SCALING, - .num_i2c_devs = 0, - .num_inputs = 1, - .inputs = { - { - .video_input = 0, - .name = "Composite", - }, - }, - }, -}; - -static const struct go7007_usb_board board_endura = { - .flags = 0, - .main_info = { - .flags = 0, - .audio_flags = GO7007_AUDIO_I2S_MODE_1 | - GO7007_AUDIO_I2S_MASTER | - GO7007_AUDIO_WORD_16, - .audio_rate = 8000, - .audio_bclk_div = 48, - .audio_main_div = 8, - .hpi_buffer_cap = 0, - .sensor_flags = GO7007_SENSOR_656 | - GO7007_SENSOR_TV, - .sensor_h_offset = 8, - .num_i2c_devs = 0, - .num_inputs = 1, - .inputs = { - { - .name = "Camera", - }, - }, - }, -}; - -static const struct go7007_usb_board board_adlink_mpg24 = { - .flags = 0, - .main_info = { - .flags = GO7007_BOARD_USE_ONBOARD_I2C, - .audio_flags = GO7007_AUDIO_I2S_MODE_1 | - GO7007_AUDIO_I2S_MASTER | - GO7007_AUDIO_WORD_16, - .audio_rate = 48000, - .audio_bclk_div = 8, - .audio_main_div = 2, - .hpi_buffer_cap = 0, - .sensor_flags = GO7007_SENSOR_656 | - GO7007_SENSOR_TV | - GO7007_SENSOR_VBI, - .num_i2c_devs = 1, - .i2c_devs = { - { - .type = "tw2804", - .addr = 0x00, /* yes, really */ - .flags = I2C_CLIENT_TEN, - .is_video = 1, - }, - }, - .num_inputs = 1, - .inputs = { - { - .name = "Composite", - }, - }, - }, -}; - -static const struct go7007_usb_board board_sensoray_2250 = { - .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, - .main_info = { - .audio_flags = GO7007_AUDIO_I2S_MODE_1 | - GO7007_AUDIO_I2S_MASTER | - GO7007_AUDIO_WORD_16, - .flags = GO7007_BOARD_HAS_AUDIO, - .audio_rate = 48000, - .audio_bclk_div = 8, - .audio_main_div = 2, - .hpi_buffer_cap = 7, - .sensor_flags = GO7007_SENSOR_656 | - GO7007_SENSOR_TV, - .num_i2c_devs = 1, - .i2c_devs = { - { - .type = "s2250", - .addr = 0x43, - .is_video = 1, - .is_audio = 1, - }, - }, - .num_inputs = 2, - .inputs = { - { - .video_input = 0, - .name = "Composite", - }, - { - .video_input = 1, - .name = "S-Video", - }, - }, - .num_aud_inputs = 3, - .aud_inputs = { - { - .audio_input = 0, - .name = "Line In", - }, - { - .audio_input = 1, - .name = "Mic", - }, - { - .audio_input = 2, - .name = "Mic Boost", - }, - }, - }, -}; - -static const struct go7007_usb_board board_ads_usbav_709 = { - .flags = GO7007_USB_EZUSB, - .main_info = { - .flags = GO7007_BOARD_HAS_AUDIO | - GO7007_BOARD_USE_ONBOARD_I2C, - .audio_flags = GO7007_AUDIO_I2S_MODE_1 | - GO7007_AUDIO_I2S_MASTER | - GO7007_AUDIO_WORD_16, - .audio_rate = 48000, - .audio_bclk_div = 8, - .audio_main_div = 2, - .hpi_buffer_cap = 7, - .sensor_flags = GO7007_SENSOR_656 | - GO7007_SENSOR_TV | - GO7007_SENSOR_VBI, - .num_i2c_devs = 1, - .i2c_devs = { - { - .type = "tw9906", - .is_video = 1, - .addr = 0x44, - }, - }, - .num_inputs = 2, - .inputs = { - { - .video_input = 0, - .name = "Composite", - }, - { - .video_input = 10, - .name = "S-Video", - }, - }, - }, -}; - -static const struct usb_device_id go7007_usb_id_table[] = { - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | - USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ - .idProduct = 0x7007, /* Product ID of GO7007SB chip */ - .bcdDevice_lo = 0x200, /* Revision number of XMen */ - .bcdDevice_hi = 0x200, - .bInterfaceClass = 255, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 255, - .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN, - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, - .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ - .idProduct = 0x7007, /* Product ID of GO7007SB chip */ - .bcdDevice_lo = 0x202, /* Revision number of Matrix II */ - .bcdDevice_hi = 0x202, - .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_II, - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, - .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ - .idProduct = 0x7007, /* Product ID of GO7007SB chip */ - .bcdDevice_lo = 0x204, /* Revision number of Matrix */ - .bcdDevice_hi = 0x204, /* Reloaded */ - .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_RELOAD, - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | - USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ - .idProduct = 0x7007, /* Product ID of GO7007SB chip */ - .bcdDevice_lo = 0x205, /* Revision number of XMen-II */ - .bcdDevice_hi = 0x205, - .bInterfaceClass = 255, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 255, - .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_II, - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, - .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ - .idProduct = 0x7007, /* Product ID of GO7007SB chip */ - .bcdDevice_lo = 0x208, /* Revision number of Star Trek */ - .bcdDevice_hi = 0x208, - .driver_info = (kernel_ulong_t)GO7007_BOARDID_STAR_TREK, - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | - USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ - .idProduct = 0x7007, /* Product ID of GO7007SB chip */ - .bcdDevice_lo = 0x209, /* Revision number of XMen-III */ - .bcdDevice_hi = 0x209, - .bInterfaceClass = 255, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 255, - .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_III, - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, - .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ - .idProduct = 0x7007, /* Product ID of GO7007SB chip */ - .bcdDevice_lo = 0x210, /* Revision number of Matrix */ - .bcdDevice_hi = 0x210, /* Revolution */ - .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_REV, - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, - .idVendor = 0x093b, /* Vendor ID of Plextor */ - .idProduct = 0xa102, /* Product ID of M402U */ - .bcdDevice_lo = 0x1, /* revision number of Blueberry */ - .bcdDevice_hi = 0x1, - .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_M402U, - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, - .idVendor = 0x093b, /* Vendor ID of Plextor */ - .idProduct = 0xa104, /* Product ID of TV402U */ - .bcdDevice_lo = 0x1, - .bcdDevice_hi = 0x1, - .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_TV402U, - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, - .idVendor = 0x10fd, /* Vendor ID of Anubis Electronics */ - .idProduct = 0xde00, /* Product ID of Lifeview LR192 */ - .bcdDevice_lo = 0x1, - .bcdDevice_hi = 0x1, - .driver_info = (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192, - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, - .idVendor = 0x1943, /* Vendor ID Sensoray */ - .idProduct = 0x2250, /* Product ID of 2250/2251 */ - .bcdDevice_lo = 0x1, - .bcdDevice_hi = 0x1, - .driver_info = (kernel_ulong_t)GO7007_BOARDID_SENSORAY_2250, - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, - .idVendor = 0x06e1, /* Vendor ID of ADS Technologies */ - .idProduct = 0x0709, /* Product ID of DVD Xpress DX2 */ - .bcdDevice_lo = 0x204, - .bcdDevice_hi = 0x204, - .driver_info = (kernel_ulong_t)GO7007_BOARDID_ADS_USBAV_709, - }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, go7007_usb_id_table); - -/********************* Driver for EZ-USB HPI interface *********************/ - -static int go7007_usb_vendor_request(struct go7007 *go, int request, - int value, int index, void *transfer_buffer, int length, int in) -{ - struct go7007_usb *usb = go->hpi_context; - int timeout = 5000; - - if (in) { - return usb_control_msg(usb->usbdev, - usb_rcvctrlpipe(usb->usbdev, 0), request, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - value, index, transfer_buffer, length, timeout); - } else { - return usb_control_msg(usb->usbdev, - usb_sndctrlpipe(usb->usbdev, 0), request, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, transfer_buffer, length, timeout); - } -} - -static int go7007_usb_interface_reset(struct go7007 *go) -{ - struct go7007_usb *usb = go->hpi_context; - u16 intr_val, intr_data; - - if (go->status == STATUS_SHUTDOWN) - return -1; - /* Reset encoder */ - if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0) - return -1; - msleep(100); - - if (usb->board->flags & GO7007_USB_EZUSB) { - /* Reset buffer in EZ-USB */ - pr_debug("resetting EZ-USB buffers\n"); - if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 || - go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0) - return -1; - - /* Reset encoder again */ - if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0) - return -1; - msleep(100); - } - - /* Wait for an interrupt to indicate successful hardware reset */ - if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || - (intr_val & ~0x1) != 0x55aa) { - dev_err(go->dev, "unable to reset the USB interface\n"); - return -1; - } - return 0; -} - -static int go7007_usb_ezusb_write_interrupt(struct go7007 *go, - int addr, int data) -{ - struct go7007_usb *usb = go->hpi_context; - int i, r; - u16 status_reg = 0; - int timeout = 500; - - pr_debug("WriteInterrupt: %04x %04x\n", addr, data); - - for (i = 0; i < 100; ++i) { - r = usb_control_msg(usb->usbdev, - usb_rcvctrlpipe(usb->usbdev, 0), 0x14, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0, HPI_STATUS_ADDR, go->usb_buf, - sizeof(status_reg), timeout); - if (r < 0) - break; - status_reg = le16_to_cpu(*((u16 *)go->usb_buf)); - if (!(status_reg & 0x0010)) - break; - msleep(10); - } - if (r < 0) - goto write_int_error; - if (i == 100) { - dev_err(go->dev, "device is hung, status reg = 0x%04x\n", status_reg); - return -1; - } - r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 0x12, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, data, - INT_PARAM_ADDR, NULL, 0, timeout); - if (r < 0) - goto write_int_error; - r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), - 0x12, USB_TYPE_VENDOR | USB_RECIP_DEVICE, addr, - INT_INDEX_ADDR, NULL, 0, timeout); - if (r < 0) - goto write_int_error; - return 0; - -write_int_error: - dev_err(go->dev, "error in WriteInterrupt: %d\n", r); - return r; -} - -static int go7007_usb_onboard_write_interrupt(struct go7007 *go, - int addr, int data) -{ - struct go7007_usb *usb = go->hpi_context; - int r; - int timeout = 500; - - pr_debug("WriteInterrupt: %04x %04x\n", addr, data); - - go->usb_buf[0] = data & 0xff; - go->usb_buf[1] = data >> 8; - go->usb_buf[2] = addr & 0xff; - go->usb_buf[3] = addr >> 8; - go->usb_buf[4] = go->usb_buf[5] = go->usb_buf[6] = go->usb_buf[7] = 0; - r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 2), 0x00, - USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0x55aa, - 0xf0f0, go->usb_buf, 8, timeout); - if (r < 0) { - dev_err(go->dev, "error in WriteInterrupt: %d\n", r); - return r; - } - return 0; -} - -static void go7007_usb_readinterrupt_complete(struct urb *urb) -{ - struct go7007 *go = (struct go7007 *)urb->context; - u16 *regs = (u16 *)urb->transfer_buffer; - int status = urb->status; - - if (status) { - if (status != -ESHUTDOWN && - go->status != STATUS_SHUTDOWN) { - dev_err(go->dev, "error in read interrupt: %d\n", urb->status); - } else { - wake_up(&go->interrupt_waitq); - return; - } - } else if (urb->actual_length != urb->transfer_buffer_length) { - dev_err(go->dev, "short read in interrupt pipe!\n"); - } else { - go->interrupt_available = 1; - go->interrupt_data = __le16_to_cpu(regs[0]); - go->interrupt_value = __le16_to_cpu(regs[1]); - pr_debug("ReadInterrupt: %04x %04x\n", - go->interrupt_value, go->interrupt_data); - } - - wake_up(&go->interrupt_waitq); -} - -static int go7007_usb_read_interrupt(struct go7007 *go) -{ - struct go7007_usb *usb = go->hpi_context; - int r; - - r = usb_submit_urb(usb->intr_urb, GFP_KERNEL); - if (r < 0) { - dev_err(go->dev, "unable to submit interrupt urb: %d\n", r); - return r; - } - return 0; -} - -static void go7007_usb_read_video_pipe_complete(struct urb *urb) -{ - struct go7007 *go = (struct go7007 *)urb->context; - int r, status = urb->status; - - if (!vb2_is_streaming(&go->vidq)) { - wake_up_interruptible(&go->frame_waitq); - return; - } - if (status) { - dev_err(go->dev, "error in video pipe: %d\n", status); - return; - } - if (urb->actual_length != urb->transfer_buffer_length) { - dev_err(go->dev, "short read in video pipe!\n"); - return; - } - go7007_parse_video_stream(go, urb->transfer_buffer, urb->actual_length); - r = usb_submit_urb(urb, GFP_ATOMIC); - if (r < 0) - dev_err(go->dev, "error in video pipe: %d\n", r); -} - -static void go7007_usb_read_audio_pipe_complete(struct urb *urb) -{ - struct go7007 *go = (struct go7007 *)urb->context; - int r, status = urb->status; - - if (!vb2_is_streaming(&go->vidq)) - return; - if (status) { - dev_err(go->dev, "error in audio pipe: %d\n", - status); - return; - } - if (urb->actual_length != urb->transfer_buffer_length) { - dev_err(go->dev, "short read in audio pipe!\n"); - return; - } - if (go->audio_deliver != NULL) - go->audio_deliver(go, urb->transfer_buffer, urb->actual_length); - r = usb_submit_urb(urb, GFP_ATOMIC); - if (r < 0) - dev_err(go->dev, "error in audio pipe: %d\n", r); -} - -static int go7007_usb_stream_start(struct go7007 *go) -{ - struct go7007_usb *usb = go->hpi_context; - int i, r; - - for (i = 0; i < 8; ++i) { - r = usb_submit_urb(usb->video_urbs[i], GFP_KERNEL); - if (r < 0) { - dev_err(go->dev, "error submitting video urb %d: %d\n", i, r); - goto video_submit_failed; - } - } - if (!go->audio_enabled) - return 0; - - for (i = 0; i < 8; ++i) { - r = usb_submit_urb(usb->audio_urbs[i], GFP_KERNEL); - if (r < 0) { - dev_err(go->dev, "error submitting audio urb %d: %d\n", i, r); - goto audio_submit_failed; - } - } - return 0; - -audio_submit_failed: - for (i = 0; i < 7; ++i) - usb_kill_urb(usb->audio_urbs[i]); -video_submit_failed: - for (i = 0; i < 8; ++i) - usb_kill_urb(usb->video_urbs[i]); - return -1; -} - -static int go7007_usb_stream_stop(struct go7007 *go) -{ - struct go7007_usb *usb = go->hpi_context; - int i; - - if (go->status == STATUS_SHUTDOWN) - return 0; - for (i = 0; i < 8; ++i) - usb_kill_urb(usb->video_urbs[i]); - if (go->audio_enabled) - for (i = 0; i < 8; ++i) - usb_kill_urb(usb->audio_urbs[i]); - return 0; -} - -static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len) -{ - struct go7007_usb *usb = go->hpi_context; - int transferred, pipe; - int timeout = 500; - - pr_debug("DownloadBuffer sending %d bytes\n", len); - - if (usb->board->flags & GO7007_USB_EZUSB) - pipe = usb_sndbulkpipe(usb->usbdev, 2); - else - pipe = usb_sndbulkpipe(usb->usbdev, 3); - - return usb_bulk_msg(usb->usbdev, pipe, data, len, - &transferred, timeout); -} - -static void go7007_usb_release(struct go7007 *go) -{ - struct go7007_usb *usb = go->hpi_context; - struct urb *vurb, *aurb; - int i; - - if (usb->intr_urb) { - usb_kill_urb(usb->intr_urb); - kfree(usb->intr_urb->transfer_buffer); - usb_free_urb(usb->intr_urb); - } - - /* Free USB-related structs */ - for (i = 0; i < 8; ++i) { - vurb = usb->video_urbs[i]; - if (vurb) { - usb_kill_urb(vurb); - kfree(vurb->transfer_buffer); - usb_free_urb(vurb); - } - aurb = usb->audio_urbs[i]; - if (aurb) { - usb_kill_urb(aurb); - kfree(aurb->transfer_buffer); - usb_free_urb(aurb); - } - } - - kfree(go->hpi_context); -} - -static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { - .interface_reset = go7007_usb_interface_reset, - .write_interrupt = go7007_usb_ezusb_write_interrupt, - .read_interrupt = go7007_usb_read_interrupt, - .stream_start = go7007_usb_stream_start, - .stream_stop = go7007_usb_stream_stop, - .send_firmware = go7007_usb_send_firmware, - .release = go7007_usb_release, -}; - -static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = { - .interface_reset = go7007_usb_interface_reset, - .write_interrupt = go7007_usb_onboard_write_interrupt, - .read_interrupt = go7007_usb_read_interrupt, - .stream_start = go7007_usb_stream_start, - .stream_stop = go7007_usb_stream_stop, - .send_firmware = go7007_usb_send_firmware, - .release = go7007_usb_release, -}; - -/********************* Driver for EZ-USB I2C adapter *********************/ - -static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter, - struct i2c_msg msgs[], int num) -{ - struct go7007 *go = i2c_get_adapdata(adapter); - struct go7007_usb *usb = go->hpi_context; - u8 *buf = go->usb_buf; - int buf_len, i; - int ret = -EIO; - - if (go->status == STATUS_SHUTDOWN) - return -ENODEV; - - mutex_lock(&usb->i2c_lock); - - for (i = 0; i < num; ++i) { - /* The hardware command is "write some bytes then read some - * bytes", so we try to coalesce a write followed by a read - * into a single USB transaction */ - if (i + 1 < num && msgs[i].addr == msgs[i + 1].addr && - !(msgs[i].flags & I2C_M_RD) && - (msgs[i + 1].flags & I2C_M_RD)) { -#ifdef GO7007_I2C_DEBUG - pr_debug("i2c write/read %d/%d bytes on %02x\n", - msgs[i].len, msgs[i + 1].len, msgs[i].addr); -#endif - buf[0] = 0x01; - buf[1] = msgs[i].len + 1; - buf[2] = msgs[i].addr << 1; - memcpy(&buf[3], msgs[i].buf, msgs[i].len); - buf_len = msgs[i].len + 3; - buf[buf_len++] = msgs[++i].len; - } else if (msgs[i].flags & I2C_M_RD) { -#ifdef GO7007_I2C_DEBUG - pr_debug("i2c read %d bytes on %02x\n", - msgs[i].len, msgs[i].addr); -#endif - buf[0] = 0x01; - buf[1] = 1; - buf[2] = msgs[i].addr << 1; - buf[3] = msgs[i].len; - buf_len = 4; - } else { -#ifdef GO7007_I2C_DEBUG - pr_debug("i2c write %d bytes on %02x\n", - msgs[i].len, msgs[i].addr); -#endif - buf[0] = 0x00; - buf[1] = msgs[i].len + 1; - buf[2] = msgs[i].addr << 1; - memcpy(&buf[3], msgs[i].buf, msgs[i].len); - buf_len = msgs[i].len + 3; - buf[buf_len++] = 0; - } - if (go7007_usb_vendor_request(go, 0x24, 0, 0, - buf, buf_len, 0) < 0) - goto i2c_done; - if (msgs[i].flags & I2C_M_RD) { - memset(buf, 0, msgs[i].len + 1); - if (go7007_usb_vendor_request(go, 0x25, 0, 0, buf, - msgs[i].len + 1, 1) < 0) - goto i2c_done; - memcpy(msgs[i].buf, buf + 1, msgs[i].len); - } - } - ret = num; - -i2c_done: - mutex_unlock(&usb->i2c_lock); - return ret; -} - -static u32 go7007_usb_functionality(struct i2c_adapter *adapter) -{ - /* No errors are reported by the hardware, so we don't bother - * supporting quick writes to avoid confusing probing */ - return (I2C_FUNC_SMBUS_EMUL) & ~I2C_FUNC_SMBUS_QUICK; -} - -static struct i2c_algorithm go7007_usb_algo = { - .master_xfer = go7007_usb_i2c_master_xfer, - .functionality = go7007_usb_functionality, -}; - -static struct i2c_adapter go7007_usb_adap_templ = { - .owner = THIS_MODULE, - .name = "WIS GO7007SB EZ-USB", - .algo = &go7007_usb_algo, -}; - -/********************* USB add/remove functions *********************/ - -static int go7007_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct go7007 *go; - struct go7007_usb *usb; - const struct go7007_usb_board *board; - struct usb_device *usbdev = interface_to_usbdev(intf); - unsigned num_i2c_devs; - char *name; - int video_pipe, i, v_urb_len; - - pr_debug("probing new GO7007 USB board\n"); - - switch (id->driver_info) { - case GO7007_BOARDID_MATRIX_II: - name = "WIS Matrix II or compatible"; - board = &board_matrix_ii; - break; - case GO7007_BOARDID_MATRIX_RELOAD: - name = "WIS Matrix Reloaded or compatible"; - board = &board_matrix_reload; - break; - case GO7007_BOARDID_MATRIX_REV: - name = "WIS Matrix Revolution or compatible"; - board = &board_matrix_revolution; - break; - case GO7007_BOARDID_STAR_TREK: - name = "WIS Star Trek or compatible"; - board = &board_star_trek; - break; - case GO7007_BOARDID_XMEN: - name = "WIS XMen or compatible"; - board = &board_xmen; - break; - case GO7007_BOARDID_XMEN_II: - name = "WIS XMen II or compatible"; - board = &board_xmen; - break; - case GO7007_BOARDID_XMEN_III: - name = "WIS XMen III or compatible"; - board = &board_xmen; - break; - case GO7007_BOARDID_PX_M402U: - name = "Plextor PX-M402U"; - board = &board_matrix_ii; - break; - case GO7007_BOARDID_PX_TV402U: - name = "Plextor PX-TV402U (unknown tuner)"; - board = &board_px_tv402u; - break; - case GO7007_BOARDID_LIFEVIEW_LR192: - dev_err(&intf->dev, "The Lifeview TV Walker Ultra is not supported. Sorry!\n"); - return -ENODEV; - name = "Lifeview TV Walker Ultra"; - board = &board_lifeview_lr192; - break; - case GO7007_BOARDID_SENSORAY_2250: - dev_info(&intf->dev, "Sensoray 2250 found\n"); - name = "Sensoray 2250/2251"; - board = &board_sensoray_2250; - break; - case GO7007_BOARDID_ADS_USBAV_709: - name = "ADS Tech DVD Xpress DX2"; - board = &board_ads_usbav_709; - break; - default: - dev_err(&intf->dev, "unknown board ID %d!\n", - (unsigned int)id->driver_info); - return -ENODEV; - } - - go = go7007_alloc(&board->main_info, &intf->dev); - if (go == NULL) - return -ENOMEM; - - usb = kzalloc(sizeof(struct go7007_usb), GFP_KERNEL); - if (usb == NULL) { - kfree(go); - return -ENOMEM; - } - - usb->board = board; - usb->usbdev = usbdev; - usb_make_path(usbdev, go->bus_info, sizeof(go->bus_info)); - go->board_id = id->driver_info; - strncpy(go->name, name, sizeof(go->name)); - if (board->flags & GO7007_USB_EZUSB) - go->hpi_ops = &go7007_usb_ezusb_hpi_ops; - else - go->hpi_ops = &go7007_usb_onboard_hpi_ops; - go->hpi_context = usb; - - /* Allocate the URB and buffer for receiving incoming interrupts */ - usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL); - if (usb->intr_urb == NULL) - goto allocfail; - usb->intr_urb->transfer_buffer = kmalloc(2*sizeof(u16), GFP_KERNEL); - if (usb->intr_urb->transfer_buffer == NULL) - goto allocfail; - - if (go->board_id == GO7007_BOARDID_SENSORAY_2250) - usb_fill_bulk_urb(usb->intr_urb, usb->usbdev, - usb_rcvbulkpipe(usb->usbdev, 4), - usb->intr_urb->transfer_buffer, 2*sizeof(u16), - go7007_usb_readinterrupt_complete, go); - else - usb_fill_int_urb(usb->intr_urb, usb->usbdev, - usb_rcvintpipe(usb->usbdev, 4), - usb->intr_urb->transfer_buffer, 2*sizeof(u16), - go7007_usb_readinterrupt_complete, go, 8); - usb_set_intfdata(intf, &go->v4l2_dev); - - /* Boot the GO7007 */ - if (go7007_boot_encoder(go, go->board_info->flags & - GO7007_BOARD_USE_ONBOARD_I2C) < 0) - goto allocfail; - - /* Register the EZ-USB I2C adapter, if we're using it */ - if (board->flags & GO7007_USB_EZUSB_I2C) { - memcpy(&go->i2c_adapter, &go7007_usb_adap_templ, - sizeof(go7007_usb_adap_templ)); - mutex_init(&usb->i2c_lock); - go->i2c_adapter.dev.parent = go->dev; - i2c_set_adapdata(&go->i2c_adapter, go); - if (i2c_add_adapter(&go->i2c_adapter) < 0) { - dev_err(go->dev, "error: i2c_add_adapter failed\n"); - goto allocfail; - } - go->i2c_adapter_online = 1; - } - - /* Pelco and Adlink reused the XMen and XMen-III vendor and product - * IDs for their own incompatible designs. We can detect XMen boards - * by probing the sensor, but there is no way to probe the sensors on - * the Pelco and Adlink designs so we default to the Adlink. If it - * is actually a Pelco, the user must set the assume_endura module - * parameter. */ - if ((go->board_id == GO7007_BOARDID_XMEN || - go->board_id == GO7007_BOARDID_XMEN_III) && - go->i2c_adapter_online) { - union i2c_smbus_data data; - - /* Check to see if register 0x0A is 0x76 */ - i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB, - I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data); - if (data.byte != 0x76) { - if (assume_endura) { - go->board_id = GO7007_BOARDID_ENDURA; - usb->board = board = &board_endura; - go->board_info = &board->main_info; - strncpy(go->name, "Pelco Endura", - sizeof(go->name)); - } else { - u16 channel; - - /* read channel number from GPIO[1:0] */ - go7007_read_addr(go, 0x3c81, &channel); - channel &= 0x3; - go->board_id = GO7007_BOARDID_ADLINK_MPG24; - usb->board = board = &board_adlink_mpg24; - go->board_info = &board->main_info; - go->channel_number = channel; - snprintf(go->name, sizeof(go->name), - "Adlink PCI-MPG24, channel #%d", - channel); - } - go7007_update_board(go); - } - } - - num_i2c_devs = go->board_info->num_i2c_devs; - - /* Probe the tuner model on the TV402U */ - if (go->board_id == GO7007_BOARDID_PX_TV402U) { - /* Board strapping indicates tuner model */ - if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3, - 1) < 0) { - dev_err(go->dev, "GPIO read failed!\n"); - goto allocfail; - } - switch (go->usb_buf[0] >> 6) { - case 1: - go->tuner_type = TUNER_SONY_BTF_PG472Z; - go->std = V4L2_STD_PAL; - strncpy(go->name, "Plextor PX-TV402U-EU", - sizeof(go->name)); - break; - case 2: - go->tuner_type = TUNER_SONY_BTF_PK467Z; - go->std = V4L2_STD_NTSC_M_JP; - num_i2c_devs -= 2; - strncpy(go->name, "Plextor PX-TV402U-JP", - sizeof(go->name)); - break; - case 3: - go->tuner_type = TUNER_SONY_BTF_PB463Z; - num_i2c_devs -= 2; - strncpy(go->name, "Plextor PX-TV402U-NA", - sizeof(go->name)); - break; - default: - pr_debug("unable to detect tuner type!\n"); - break; - } - /* Configure tuner mode selection inputs connected - * to the EZ-USB GPIO output pins */ - if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0, - NULL, 0, 0) < 0) { - dev_err(go->dev, "GPIO write failed!\n"); - goto allocfail; - } - } - - /* Print a nasty message if the user attempts to use a USB2.0 device in - * a USB1.1 port. There will be silent corruption of the stream. */ - if ((board->flags & GO7007_USB_EZUSB) && - usbdev->speed != USB_SPEED_HIGH) - dev_err(go->dev, "*** WARNING *** This device must be connected to a USB 2.0 port! Attempting to capture video through a USB 1.1 port will result in stream corruption, even at low bitrates!\n"); - - /* Allocate the URBs and buffers for receiving the video stream */ - if (board->flags & GO7007_USB_EZUSB) { - v_urb_len = 1024; - video_pipe = usb_rcvbulkpipe(usb->usbdev, 6); - } else { - v_urb_len = 512; - video_pipe = usb_rcvbulkpipe(usb->usbdev, 1); - } - for (i = 0; i < 8; ++i) { - usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); - if (usb->video_urbs[i] == NULL) - goto allocfail; - usb->video_urbs[i]->transfer_buffer = - kmalloc(v_urb_len, GFP_KERNEL); - if (usb->video_urbs[i]->transfer_buffer == NULL) - goto allocfail; - usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe, - usb->video_urbs[i]->transfer_buffer, v_urb_len, - go7007_usb_read_video_pipe_complete, go); - } - - /* Allocate the URBs and buffers for receiving the audio stream */ - if ((board->flags & GO7007_USB_EZUSB) && - (board->flags & GO7007_BOARD_HAS_AUDIO)) { - for (i = 0; i < 8; ++i) { - usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); - if (usb->audio_urbs[i] == NULL) - goto allocfail; - usb->audio_urbs[i]->transfer_buffer = kmalloc(4096, - GFP_KERNEL); - if (usb->audio_urbs[i]->transfer_buffer == NULL) - goto allocfail; - usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev, - usb_rcvbulkpipe(usb->usbdev, 8), - usb->audio_urbs[i]->transfer_buffer, 4096, - go7007_usb_read_audio_pipe_complete, go); - } - } - - /* Do any final GO7007 initialization, then register the - * V4L2 and ALSA interfaces */ - if (go7007_register_encoder(go, num_i2c_devs) < 0) - goto allocfail; - - go->status = STATUS_ONLINE; - return 0; - -allocfail: - go7007_usb_release(go); - kfree(go); - return -ENOMEM; -} - -static void go7007_usb_disconnect(struct usb_interface *intf) -{ - struct go7007 *go = to_go7007(usb_get_intfdata(intf)); - - mutex_lock(&go->queue_lock); - mutex_lock(&go->serialize_lock); - - if (go->audio_enabled) - go7007_snd_remove(go); - - go->status = STATUS_SHUTDOWN; - v4l2_device_disconnect(&go->v4l2_dev); - video_unregister_device(&go->vdev); - mutex_unlock(&go->serialize_lock); - mutex_unlock(&go->queue_lock); - - v4l2_device_put(&go->v4l2_dev); -} - -static struct usb_driver go7007_usb_driver = { - .name = "go7007", - .probe = go7007_usb_probe, - .disconnect = go7007_usb_disconnect, - .id_table = go7007_usb_id_table, -}; - -module_usb_driver(go7007_usb_driver); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/media/go7007/go7007-v4l2.c b/drivers/staging/media/go7007/go7007-v4l2.c deleted file mode 100644 index da7b5493e13e..000000000000 --- a/drivers/staging/media/go7007/go7007-v4l2.c +++ /dev/null @@ -1,1055 +0,0 @@ -/* - * Copyright (C) 2005-2006 Micronas USA Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * 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/delay.h> -#include <linux/sched.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/fs.h> -#include <linux/unistd.h> -#include <linux/time.h> -#include <linux/vmalloc.h> -#include <linux/pagemap.h> -#include <linux/i2c.h> -#include <linux/mutex.h> -#include <linux/uaccess.h> -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-subdev.h> -#include <media/v4l2-event.h> -#include <media/videobuf2-vmalloc.h> -#include <media/saa7115.h> - -#include "go7007.h" -#include "go7007-priv.h" - -#define call_all(dev, o, f, args...) \ - v4l2_device_call_until_err(dev, 0, o, f, ##args) - -static bool valid_pixelformat(u32 pixelformat) -{ - switch (pixelformat) { - case V4L2_PIX_FMT_MJPEG: - case V4L2_PIX_FMT_MPEG1: - case V4L2_PIX_FMT_MPEG2: - case V4L2_PIX_FMT_MPEG4: - return true; - default: - return false; - } -} - -static u32 get_frame_type_flag(struct go7007_buffer *vb, int format) -{ - u8 *ptr = vb2_plane_vaddr(&vb->vb, 0); - - switch (format) { - case V4L2_PIX_FMT_MJPEG: - return V4L2_BUF_FLAG_KEYFRAME; - case V4L2_PIX_FMT_MPEG4: - switch ((ptr[vb->frame_offset + 4] >> 6) & 0x3) { - case 0: - return V4L2_BUF_FLAG_KEYFRAME; - case 1: - return V4L2_BUF_FLAG_PFRAME; - case 2: - return V4L2_BUF_FLAG_BFRAME; - default: - return 0; - } - case V4L2_PIX_FMT_MPEG1: - case V4L2_PIX_FMT_MPEG2: - switch ((ptr[vb->frame_offset + 5] >> 3) & 0x7) { - case 1: - return V4L2_BUF_FLAG_KEYFRAME; - case 2: - return V4L2_BUF_FLAG_PFRAME; - case 3: - return V4L2_BUF_FLAG_BFRAME; - default: - return 0; - } - } - - return 0; -} - -static void get_resolution(struct go7007 *go, int *width, int *height) -{ - switch (go->standard) { - case GO7007_STD_NTSC: - *width = 720; - *height = 480; - break; - case GO7007_STD_PAL: - *width = 720; - *height = 576; - break; - case GO7007_STD_OTHER: - default: - *width = go->board_info->sensor_width; - *height = go->board_info->sensor_height; - break; - } -} - -static void set_formatting(struct go7007 *go) -{ - if (go->format == V4L2_PIX_FMT_MJPEG) { - go->pali = 0; - go->aspect_ratio = GO7007_RATIO_1_1; - go->gop_size = 0; - go->ipb = 0; - go->closed_gop = 0; - go->repeat_seqhead = 0; - go->seq_header_enable = 0; - go->gop_header_enable = 0; - go->dvd_mode = 0; - return; - } - - switch (go->format) { - case V4L2_PIX_FMT_MPEG1: - go->pali = 0; - break; - default: - case V4L2_PIX_FMT_MPEG2: - go->pali = 0x48; - break; - case V4L2_PIX_FMT_MPEG4: - /* For future reference: this is the list of MPEG4 - * profiles that are available, although they are - * untested: - * - * Profile pali - * -------------- ---- - * PROFILE_S_L0 0x08 - * PROFILE_S_L1 0x01 - * PROFILE_S_L2 0x02 - * PROFILE_S_L3 0x03 - * PROFILE_ARTS_L1 0x91 - * PROFILE_ARTS_L2 0x92 - * PROFILE_ARTS_L3 0x93 - * PROFILE_ARTS_L4 0x94 - * PROFILE_AS_L0 0xf0 - * PROFILE_AS_L1 0xf1 - * PROFILE_AS_L2 0xf2 - * PROFILE_AS_L3 0xf3 - * PROFILE_AS_L4 0xf4 - * PROFILE_AS_L5 0xf5 - */ - go->pali = 0xf5; - break; - } - go->gop_size = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_size); - go->closed_gop = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_closure); - go->ipb = v4l2_ctrl_g_ctrl(go->mpeg_video_b_frames) != 0; - go->bitrate = v4l2_ctrl_g_ctrl(go->mpeg_video_bitrate); - go->repeat_seqhead = v4l2_ctrl_g_ctrl(go->mpeg_video_rep_seqheader); - go->gop_header_enable = 1; - go->dvd_mode = 0; - if (go->format == V4L2_PIX_FMT_MPEG2) - go->dvd_mode = - go->bitrate == 9800000 && - go->gop_size == 15 && - go->ipb == 0 && - go->repeat_seqhead == 1 && - go->closed_gop; - - switch (v4l2_ctrl_g_ctrl(go->mpeg_video_aspect_ratio)) { - default: - case V4L2_MPEG_VIDEO_ASPECT_1x1: - go->aspect_ratio = GO7007_RATIO_1_1; - break; - case V4L2_MPEG_VIDEO_ASPECT_4x3: - go->aspect_ratio = GO7007_RATIO_4_3; - break; - case V4L2_MPEG_VIDEO_ASPECT_16x9: - go->aspect_ratio = GO7007_RATIO_16_9; - break; - } -} - -static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try) -{ - int sensor_height = 0, sensor_width = 0; - int width, height, i; - - if (fmt != NULL && !valid_pixelformat(fmt->fmt.pix.pixelformat)) - return -EINVAL; - - get_resolution(go, &sensor_width, &sensor_height); - - if (fmt == NULL) { - width = sensor_width; - height = sensor_height; - } else if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) { - if (fmt->fmt.pix.width > sensor_width) - width = sensor_width; - else if (fmt->fmt.pix.width < 144) - width = 144; - else - width = fmt->fmt.pix.width & ~0x0f; - - if (fmt->fmt.pix.height > sensor_height) - height = sensor_height; - else if (fmt->fmt.pix.height < 96) - height = 96; - else - height = fmt->fmt.pix.height & ~0x0f; - } else { - width = fmt->fmt.pix.width; - - if (width <= sensor_width / 4) { - width = sensor_width / 4; - height = sensor_height / 4; - } else if (width <= sensor_width / 2) { - width = sensor_width / 2; - height = sensor_height / 2; - } else { - width = sensor_width; - height = sensor_height; - } - width &= ~0xf; - height &= ~0xf; - } - - if (fmt != NULL) { - u32 pixelformat = fmt->fmt.pix.pixelformat; - - memset(fmt, 0, sizeof(*fmt)); - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt->fmt.pix.width = width; - fmt->fmt.pix.height = height; - fmt->fmt.pix.pixelformat = pixelformat; - fmt->fmt.pix.field = V4L2_FIELD_NONE; - fmt->fmt.pix.bytesperline = 0; - fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE; - fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - } - - if (try) - return 0; - - if (fmt) - go->format = fmt->fmt.pix.pixelformat; - go->width = width; - go->height = height; - go->encoder_h_offset = go->board_info->sensor_h_offset; - go->encoder_v_offset = go->board_info->sensor_v_offset; - for (i = 0; i < 4; ++i) - go->modet[i].enable = 0; - for (i = 0; i < 1624; ++i) - go->modet_map[i] = 0; - - if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) { - struct v4l2_mbus_framefmt mbus_fmt; - - mbus_fmt.code = V4L2_MBUS_FMT_FIXED; - mbus_fmt.width = fmt ? fmt->fmt.pix.width : width; - mbus_fmt.height = height; - go->encoder_h_halve = 0; - go->encoder_v_halve = 0; - go->encoder_subsample = 0; - call_all(&go->v4l2_dev, video, s_mbus_fmt, &mbus_fmt); - } else { - if (width <= sensor_width / 4) { - go->encoder_h_halve = 1; - go->encoder_v_halve = 1; - go->encoder_subsample = 1; - } else if (width <= sensor_width / 2) { - go->encoder_h_halve = 1; - go->encoder_v_halve = 1; - go->encoder_subsample = 0; - } else { - go->encoder_h_halve = 0; - go->encoder_v_halve = 0; - go->encoder_subsample = 0; - } - } - return 0; -} - -#if 0 -static int clip_to_modet_map(struct go7007 *go, int region, - struct v4l2_clip *clip_list) -{ - struct v4l2_clip clip, *clip_ptr; - int x, y, mbnum; - - /* Check if coordinates are OK and if any macroblocks are already - * used by other regions (besides 0) */ - clip_ptr = clip_list; - while (clip_ptr) { - if (copy_from_user(&clip, clip_ptr, sizeof(clip))) - return -EFAULT; - if (clip.c.left < 0 || (clip.c.left & 0xF) || - clip.c.width <= 0 || (clip.c.width & 0xF)) - return -EINVAL; - if (clip.c.left + clip.c.width > go->width) - return -EINVAL; - if (clip.c.top < 0 || (clip.c.top & 0xF) || - clip.c.height <= 0 || (clip.c.height & 0xF)) - return -EINVAL; - if (clip.c.top + clip.c.height > go->height) - return -EINVAL; - for (y = 0; y < clip.c.height; y += 16) - for (x = 0; x < clip.c.width; x += 16) { - mbnum = (go->width >> 4) * - ((clip.c.top + y) >> 4) + - ((clip.c.left + x) >> 4); - if (go->modet_map[mbnum] != 0 && - go->modet_map[mbnum] != region) - return -EBUSY; - } - clip_ptr = clip.next; - } - - /* Clear old region macroblocks */ - for (mbnum = 0; mbnum < 1624; ++mbnum) - if (go->modet_map[mbnum] == region) - go->modet_map[mbnum] = 0; - - /* Claim macroblocks in this list */ - clip_ptr = clip_list; - while (clip_ptr) { - if (copy_from_user(&clip, clip_ptr, sizeof(clip))) - return -EFAULT; - for (y = 0; y < clip.c.height; y += 16) - for (x = 0; x < clip.c.width; x += 16) { - mbnum = (go->width >> 4) * - ((clip.c.top + y) >> 4) + - ((clip.c.left + x) >> 4); - go->modet_map[mbnum] = region; - } - clip_ptr = clip.next; - } - return 0; -} -#endif - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct go7007 *go = video_drvdata(file); - - strlcpy(cap->driver, "go7007", sizeof(cap->driver)); - strlcpy(cap->card, go->name, sizeof(cap->card)); - strlcpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info)); - - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - - if (go->board_info->num_aud_inputs) - cap->device_caps |= V4L2_CAP_AUDIO; - if (go->board_info->flags & GO7007_BOARD_HAS_TUNER) - cap->device_caps |= V4L2_CAP_TUNER; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *fmt) -{ - char *desc = NULL; - - switch (fmt->index) { - case 0: - fmt->pixelformat = V4L2_PIX_FMT_MJPEG; - desc = "Motion JPEG"; - break; - case 1: - fmt->pixelformat = V4L2_PIX_FMT_MPEG1; - desc = "MPEG-1 ES"; - break; - case 2: - fmt->pixelformat = V4L2_PIX_FMT_MPEG2; - desc = "MPEG-2 ES"; - break; - case 3: - fmt->pixelformat = V4L2_PIX_FMT_MPEG4; - desc = "MPEG-4 ES"; - break; - default: - return -EINVAL; - } - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt->flags = V4L2_FMT_FLAG_COMPRESSED; - - strncpy(fmt->description, desc, sizeof(fmt->description)); - - return 0; -} - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct go7007 *go = video_drvdata(file); - - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt->fmt.pix.width = go->width; - fmt->fmt.pix.height = go->height; - fmt->fmt.pix.pixelformat = go->format; - fmt->fmt.pix.field = V4L2_FIELD_NONE; - fmt->fmt.pix.bytesperline = 0; - fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE; - fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - - return 0; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct go7007 *go = video_drvdata(file); - - return set_capture_size(go, fmt, 1); -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct go7007 *go = video_drvdata(file); - - if (vb2_is_busy(&go->vidq)) - return -EBUSY; - - return set_capture_size(go, fmt, 0); -} - -static int go7007_queue_setup(struct vb2_queue *q, - const struct v4l2_format *fmt, - unsigned int *num_buffers, unsigned int *num_planes, - unsigned int sizes[], void *alloc_ctxs[]) -{ - sizes[0] = GO7007_BUF_SIZE; - *num_planes = 1; - - if (*num_buffers < 2) - *num_buffers = 2; - - return 0; -} - -static void go7007_buf_queue(struct vb2_buffer *vb) -{ - struct vb2_queue *vq = vb->vb2_queue; - struct go7007 *go = vb2_get_drv_priv(vq); - struct go7007_buffer *go7007_vb = - container_of(vb, struct go7007_buffer, vb); - unsigned long flags; - - spin_lock_irqsave(&go->spinlock, flags); - list_add_tail(&go7007_vb->list, &go->vidq_active); - spin_unlock_irqrestore(&go->spinlock, flags); -} - -static int go7007_buf_prepare(struct vb2_buffer *vb) -{ - struct go7007_buffer *go7007_vb = - container_of(vb, struct go7007_buffer, vb); - - go7007_vb->modet_active = 0; - go7007_vb->frame_offset = 0; - vb->v4l2_planes[0].bytesused = 0; - return 0; -} - -static void go7007_buf_finish(struct vb2_buffer *vb) -{ - struct vb2_queue *vq = vb->vb2_queue; - struct go7007 *go = vb2_get_drv_priv(vq); - struct go7007_buffer *go7007_vb = - container_of(vb, struct go7007_buffer, vb); - u32 frame_type_flag = get_frame_type_flag(go7007_vb, go->format); - struct v4l2_buffer *buf = &vb->v4l2_buf; - - buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME | - V4L2_BUF_FLAG_PFRAME); - buf->flags |= frame_type_flag; - buf->field = V4L2_FIELD_NONE; -} - -static int go7007_start_streaming(struct vb2_queue *q, unsigned int count) -{ - struct go7007 *go = vb2_get_drv_priv(q); - int ret; - - set_formatting(go); - mutex_lock(&go->hw_lock); - go->next_seq = 0; - go->active_buf = NULL; - q->streaming = 1; - if (go7007_start_encoder(go) < 0) - ret = -EIO; - else - ret = 0; - mutex_unlock(&go->hw_lock); - if (ret) { - q->streaming = 0; - return ret; - } - call_all(&go->v4l2_dev, video, s_stream, 1); - v4l2_ctrl_grab(go->mpeg_video_gop_size, true); - v4l2_ctrl_grab(go->mpeg_video_gop_closure, true); - v4l2_ctrl_grab(go->mpeg_video_bitrate, true); - v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, true); - /* Turn on Capture LED */ - if (go->board_id == GO7007_BOARDID_ADS_USBAV_709) - go7007_write_addr(go, 0x3c82, 0x0005); - return ret; -} - -static void go7007_stop_streaming(struct vb2_queue *q) -{ - struct go7007 *go = vb2_get_drv_priv(q); - unsigned long flags; - - q->streaming = 0; - go7007_stream_stop(go); - mutex_lock(&go->hw_lock); - go7007_reset_encoder(go); - mutex_unlock(&go->hw_lock); - call_all(&go->v4l2_dev, video, s_stream, 0); - - spin_lock_irqsave(&go->spinlock, flags); - INIT_LIST_HEAD(&go->vidq_active); - spin_unlock_irqrestore(&go->spinlock, flags); - v4l2_ctrl_grab(go->mpeg_video_gop_size, false); - v4l2_ctrl_grab(go->mpeg_video_gop_closure, false); - v4l2_ctrl_grab(go->mpeg_video_bitrate, false); - v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, false); - /* Turn on Capture LED */ - if (go->board_id == GO7007_BOARDID_ADS_USBAV_709) - go7007_write_addr(go, 0x3c82, 0x000d); -} - -static struct vb2_ops go7007_video_qops = { - .queue_setup = go7007_queue_setup, - .buf_queue = go7007_buf_queue, - .buf_prepare = go7007_buf_prepare, - .buf_finish = go7007_buf_finish, - .start_streaming = go7007_start_streaming, - .stop_streaming = go7007_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -static int vidioc_g_parm(struct file *filp, void *priv, - struct v4l2_streamparm *parm) -{ - struct go7007 *go = video_drvdata(filp); - struct v4l2_fract timeperframe = { - .numerator = 1001 * go->fps_scale, - .denominator = go->sensor_framerate, - }; - - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - parm->parm.capture.readbuffers = 2; - parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; - parm->parm.capture.timeperframe = timeperframe; - - return 0; -} - -static int vidioc_s_parm(struct file *filp, void *priv, - struct v4l2_streamparm *parm) -{ - struct go7007 *go = video_drvdata(filp); - unsigned int n, d; - - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - n = go->sensor_framerate * - parm->parm.capture.timeperframe.numerator; - d = 1001 * parm->parm.capture.timeperframe.denominator; - if (n != 0 && d != 0 && n > d) - go->fps_scale = (n + d/2) / d; - else - go->fps_scale = 1; - - return vidioc_g_parm(filp, priv, parm); -} - -/* VIDIOC_ENUMSTD on go7007 were used for enumerating the supported fps and - its resolution, when the device is not connected to TV. - This is were an API abuse, probably used by the lack of specific IOCTL's to - enumerate it, by the time the driver was written. - - However, since kernel 2.6.19, two new ioctls (VIDIOC_ENUM_FRAMEINTERVALS - and VIDIOC_ENUM_FRAMESIZES) were added for this purpose. - - The two functions below implement the newer ioctls -*/ -static int vidioc_enum_framesizes(struct file *filp, void *priv, - struct v4l2_frmsizeenum *fsize) -{ - struct go7007 *go = video_drvdata(filp); - int width, height; - - if (fsize->index > 2) - return -EINVAL; - - if (!valid_pixelformat(fsize->pixel_format)) - return -EINVAL; - - get_resolution(go, &width, &height); - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fsize->discrete.width = (width >> fsize->index) & ~0xf; - fsize->discrete.height = (height >> fsize->index) & ~0xf; - return 0; -} - -static int vidioc_enum_frameintervals(struct file *filp, void *priv, - struct v4l2_frmivalenum *fival) -{ - struct go7007 *go = video_drvdata(filp); - int width, height; - int i; - - if (fival->index > 4) - return -EINVAL; - - if (!valid_pixelformat(fival->pixel_format)) - return -EINVAL; - - if (!(go->board_info->sensor_flags & GO7007_SENSOR_SCALING)) { - get_resolution(go, &width, &height); - for (i = 0; i <= 2; i++) - if (fival->width == ((width >> i) & ~0xf) && - fival->height == ((height >> i) & ~0xf)) - break; - if (i > 2) - return -EINVAL; - } - fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; - fival->discrete.numerator = 1001 * (fival->index + 1); - fival->discrete.denominator = go->sensor_framerate; - return 0; -} - -static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std) -{ - struct go7007 *go = video_drvdata(file); - - *std = go->std; - return 0; -} - -static int go7007_s_std(struct go7007 *go) -{ - if (go->std & V4L2_STD_625_50) { - go->standard = GO7007_STD_PAL; - go->sensor_framerate = 25025; - } else { - go->standard = GO7007_STD_NTSC; - go->sensor_framerate = 30000; - } - - call_all(&go->v4l2_dev, video, s_std, go->std); - set_capture_size(go, NULL, 0); - return 0; -} - -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std) -{ - struct go7007 *go = video_drvdata(file); - - if (vb2_is_busy(&go->vidq)) - return -EBUSY; - - go->std = std; - - return go7007_s_std(go); -} - -static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std) -{ - struct go7007 *go = video_drvdata(file); - - return call_all(&go->v4l2_dev, video, querystd, std); -} - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *inp) -{ - struct go7007 *go = video_drvdata(file); - - if (inp->index >= go->board_info->num_inputs) - return -EINVAL; - - strncpy(inp->name, go->board_info->inputs[inp->index].name, - sizeof(inp->name)); - - /* If this board has a tuner, it will be the first input */ - if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) && - inp->index == 0) - inp->type = V4L2_INPUT_TYPE_TUNER; - else - inp->type = V4L2_INPUT_TYPE_CAMERA; - - if (go->board_info->num_aud_inputs) - inp->audioset = (1 << go->board_info->num_aud_inputs) - 1; - else - inp->audioset = 0; - inp->tuner = 0; - if (go->board_info->sensor_flags & GO7007_SENSOR_TV) - inp->std = video_devdata(file)->tvnorms; - else - inp->std = 0; - - return 0; -} - - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *input) -{ - struct go7007 *go = video_drvdata(file); - - *input = go->input; - - return 0; -} - -static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) -{ - struct go7007 *go = video_drvdata(file); - - if (a->index >= go->board_info->num_aud_inputs) - return -EINVAL; - strlcpy(a->name, go->board_info->aud_inputs[a->index].name, - sizeof(a->name)); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - -static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) -{ - struct go7007 *go = video_drvdata(file); - - a->index = go->aud_input; - strlcpy(a->name, go->board_info->aud_inputs[go->aud_input].name, - sizeof(a->name)); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - -static int vidioc_s_audio(struct file *file, void *fh, - const struct v4l2_audio *a) -{ - struct go7007 *go = video_drvdata(file); - - if (a->index >= go->board_info->num_aud_inputs) - return -EINVAL; - go->aud_input = a->index; - v4l2_subdev_call(go->sd_audio, audio, s_routing, - go->board_info->aud_inputs[go->aud_input].audio_input, 0, 0); - return 0; -} - -static void go7007_s_input(struct go7007 *go) -{ - unsigned int input = go->input; - - v4l2_subdev_call(go->sd_video, video, s_routing, - go->board_info->inputs[input].video_input, 0, - go->board_info->video_config); - if (go->board_info->num_aud_inputs) { - int aud_input = go->board_info->inputs[input].audio_index; - - v4l2_subdev_call(go->sd_audio, audio, s_routing, - go->board_info->aud_inputs[aud_input].audio_input, 0, 0); - go->aud_input = aud_input; - } -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int input) -{ - struct go7007 *go = video_drvdata(file); - - if (input >= go->board_info->num_inputs) - return -EINVAL; - if (vb2_is_busy(&go->vidq)) - return -EBUSY; - - go->input = input; - go7007_s_input(go); - - return 0; -} - -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct go7007 *go = video_drvdata(file); - - if (t->index != 0) - return -EINVAL; - - strlcpy(t->name, "Tuner", sizeof(t->name)); - return call_all(&go->v4l2_dev, tuner, g_tuner, t); -} - -static int vidioc_s_tuner(struct file *file, void *priv, - const struct v4l2_tuner *t) -{ - struct go7007 *go = video_drvdata(file); - - if (t->index != 0) - return -EINVAL; - - return call_all(&go->v4l2_dev, tuner, s_tuner, t); -} - -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct go7007 *go = video_drvdata(file); - - if (f->tuner) - return -EINVAL; - - return call_all(&go->v4l2_dev, tuner, g_frequency, f); -} - -static int vidioc_s_frequency(struct file *file, void *priv, - const struct v4l2_frequency *f) -{ - struct go7007 *go = video_drvdata(file); - - if (f->tuner) - return -EINVAL; - - return call_all(&go->v4l2_dev, tuner, s_frequency, f); -} - -static int vidioc_log_status(struct file *file, void *priv) -{ - struct go7007 *go = video_drvdata(file); - - v4l2_ctrl_log_status(file, priv); - return call_all(&go->v4l2_dev, core, log_status); -} - -/* FIXME: - Those ioctls are private, and not needed, since several standard - extended controls already provide streaming control. - So, those ioctls should be converted into vidioc_g_ext_ctrls() - and vidioc_s_ext_ctrls() - */ - -#if 0 - case GO7007IOC_S_MD_PARAMS: - { - struct go7007_md_params *mdp = arg; - - if (mdp->region > 3) - return -EINVAL; - if (mdp->trigger > 0) { - go->modet[mdp->region].pixel_threshold = - mdp->pixel_threshold >> 1; - go->modet[mdp->region].motion_threshold = - mdp->motion_threshold >> 1; - go->modet[mdp->region].mb_threshold = - mdp->trigger >> 1; - go->modet[mdp->region].enable = 1; - } else - go->modet[mdp->region].enable = 0; - /* fall-through */ - } - case GO7007IOC_S_MD_REGION: - { - struct go7007_md_region *region = arg; - - if (region->region < 1 || region->region > 3) - return -EINVAL; - return clip_to_modet_map(go, region->region, region->clips); - } -#endif - -static struct v4l2_file_operations go7007_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = vb2_fop_release, - .unlocked_ioctl = video_ioctl2, - .read = vb2_fop_read, - .mmap = vb2_fop_mmap, - .poll = vb2_fop_poll, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_g_std = vidioc_g_std, - .vidioc_s_std = vidioc_s_std, - .vidioc_querystd = vidioc_querystd, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_enumaudio = vidioc_enumaudio, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_g_parm = vidioc_g_parm, - .vidioc_s_parm = vidioc_s_parm, - .vidioc_enum_framesizes = vidioc_enum_framesizes, - .vidioc_enum_frameintervals = vidioc_enum_frameintervals, - .vidioc_log_status = vidioc_log_status, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static struct video_device go7007_template = { - .name = "go7007", - .fops = &go7007_fops, - .release = video_device_release_empty, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = V4L2_STD_ALL, -}; - -int go7007_v4l2_ctrl_init(struct go7007 *go) -{ - struct v4l2_ctrl_handler *hdl = &go->hdl; - struct v4l2_ctrl *ctrl; - - v4l2_ctrl_handler_init(hdl, 13); - go->mpeg_video_gop_size = v4l2_ctrl_new_std(hdl, NULL, - V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, 34, 1, 15); - go->mpeg_video_gop_closure = v4l2_ctrl_new_std(hdl, NULL, - V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1); - go->mpeg_video_bitrate = v4l2_ctrl_new_std(hdl, NULL, - V4L2_CID_MPEG_VIDEO_BITRATE, - 64000, 10000000, 1, 9800000); - go->mpeg_video_b_frames = v4l2_ctrl_new_std(hdl, NULL, - V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 2, 2, 0); - go->mpeg_video_rep_seqheader = v4l2_ctrl_new_std(hdl, NULL, - V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, 0, 1, 1, 1); - - go->mpeg_video_aspect_ratio = v4l2_ctrl_new_std_menu(hdl, NULL, - V4L2_CID_MPEG_VIDEO_ASPECT, - V4L2_MPEG_VIDEO_ASPECT_16x9, 0, - V4L2_MPEG_VIDEO_ASPECT_1x1); - ctrl = v4l2_ctrl_new_std(hdl, NULL, - V4L2_CID_JPEG_ACTIVE_MARKER, 0, - V4L2_JPEG_ACTIVE_MARKER_DQT | - V4L2_JPEG_ACTIVE_MARKER_DHT, 0, - V4L2_JPEG_ACTIVE_MARKER_DQT | - V4L2_JPEG_ACTIVE_MARKER_DHT); - if (ctrl) - ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; - if (hdl->error) { - int rv = hdl->error; - - v4l2_err(&go->v4l2_dev, "Could not register controls\n"); - return rv; - } - go->v4l2_dev.ctrl_handler = hdl; - return 0; -} - -int go7007_v4l2_init(struct go7007 *go) -{ - struct video_device *vdev = &go->vdev; - int rv; - - mutex_init(&go->serialize_lock); - mutex_init(&go->queue_lock); - - INIT_LIST_HEAD(&go->vidq_active); - go->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - go->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; - go->vidq.ops = &go7007_video_qops; - go->vidq.mem_ops = &vb2_vmalloc_memops; - go->vidq.drv_priv = go; - go->vidq.buf_struct_size = sizeof(struct go7007_buffer); - go->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - go->vidq.lock = &go->queue_lock; - rv = vb2_queue_init(&go->vidq); - if (rv) - return rv; - *vdev = go7007_template; - vdev->lock = &go->serialize_lock; - vdev->queue = &go->vidq; - set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags); - video_set_drvdata(vdev, go); - vdev->v4l2_dev = &go->v4l2_dev; - if (!v4l2_device_has_op(&go->v4l2_dev, video, querystd)) - v4l2_disable_ioctl(vdev, VIDIOC_QUERYSTD); - if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) { - v4l2_disable_ioctl(vdev, VIDIOC_S_FREQUENCY); - v4l2_disable_ioctl(vdev, VIDIOC_G_FREQUENCY); - v4l2_disable_ioctl(vdev, VIDIOC_S_TUNER); - v4l2_disable_ioctl(vdev, VIDIOC_G_TUNER); - } else { - struct v4l2_frequency f = { - .type = V4L2_TUNER_ANALOG_TV, - .frequency = 980, - }; - - call_all(&go->v4l2_dev, tuner, s_frequency, &f); - } - if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV)) { - v4l2_disable_ioctl(vdev, VIDIOC_G_STD); - v4l2_disable_ioctl(vdev, VIDIOC_S_STD); - vdev->tvnorms = 0; - } - if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) - v4l2_disable_ioctl(vdev, VIDIOC_ENUM_FRAMESIZES); - if (go->board_info->num_aud_inputs == 0) { - v4l2_disable_ioctl(vdev, VIDIOC_G_AUDIO); - v4l2_disable_ioctl(vdev, VIDIOC_S_AUDIO); - v4l2_disable_ioctl(vdev, VIDIOC_ENUMAUDIO); - } - /* Setup correct crystal frequency on this board */ - if (go->board_info->sensor_flags & GO7007_SENSOR_SAA7115) - v4l2_subdev_call(go->sd_video, video, s_crystal_freq, - SAA7115_FREQ_24_576_MHZ, - SAA7115_FREQ_FL_APLL | SAA7115_FREQ_FL_UCGC | - SAA7115_FREQ_FL_DOUBLE_ASCLK); - go7007_s_input(go); - if (go->board_info->sensor_flags & GO7007_SENSOR_TV) - go7007_s_std(go); - rv = video_register_device(vdev, VFL_TYPE_GRABBER, -1); - if (rv < 0) - return rv; - dev_info(go->dev, "registered device %s [v4l2]\n", - video_device_node_name(vdev)); - - return 0; -} - -void go7007_v4l2_remove(struct go7007 *go) -{ - v4l2_ctrl_handler_free(&go->hdl); -} diff --git a/drivers/staging/media/go7007/go7007.h b/drivers/staging/media/go7007/go7007.h deleted file mode 100644 index 54b989738982..000000000000 --- a/drivers/staging/media/go7007/go7007.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2005-2006 Micronas USA Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and the associated README documentation file (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -struct go7007_md_params { - __u16 region; - __u16 trigger; - __u16 pixel_threshold; - __u16 motion_threshold; - __u32 reserved[8]; -}; - -struct go7007_md_region { - __u16 region; - __u16 flags; - struct v4l2_clip *clips; - __u32 reserved[8]; -}; - -#define GO7007IOC_S_MD_PARAMS _IOWR('V', BASE_VIDIOC_PRIVATE + 6, \ - struct go7007_md_params) -#define GO7007IOC_G_MD_PARAMS _IOR('V', BASE_VIDIOC_PRIVATE + 7, \ - struct go7007_md_params) -#define GO7007IOC_S_MD_REGION _IOW('V', BASE_VIDIOC_PRIVATE + 8, \ - struct go7007_md_region) diff --git a/drivers/staging/media/go7007/go7007.txt b/drivers/staging/media/go7007/go7007.txt deleted file mode 100644 index c8e5eb09d385..000000000000 --- a/drivers/staging/media/go7007/go7007.txt +++ /dev/null @@ -1,478 +0,0 @@ -This is a driver for the WIS GO7007SB multi-format video encoder. - -Pete Eberlein <pete@sensoray.com> - -The driver was originally released under the GPL and is currently hosted at: -http://nikosapi.org/wiki/index.php/WIS_Go7007_Linux_driver -The go7007 firmware can be acquired from the package on the site above. - -I've modified the driver to support the following Video4Linux2 MPEG -controls, with acceptable values: - -V4L2_CID_MPEG_STREAM_TYPE V4L2_MPEG_STREAM_TYPE_MPEG2_DVD - V4L2_MPEG_STREAM_TYPE_MPEG_ELEM -V4L2_CID_MPEG_VIDEO_ENCODING V4L2_MPEG_VIDEO_ENCODING_MPEG_1 - V4L2_MPEG_VIDEO_ENCODING_MPEG_2 - V4L2_MPEG_VIDEO_ENCODING_MPEG_4 -V4L2_CID_MPEG_VIDEO_ASPECT V4L2_MPEG_VIDEO_ASPECT_1x1 - V4L2_MPEG_VIDEO_ASPECT_4x3 - V4L2_MPEG_VIDEO_ASPECT_16x9 -V4L2_CID_MPEG_VIDEO_GOP_SIZE integer -V4L2_CID_MPEG_VIDEO_BITRATE 64000 .. 10000000 - -These should be used instead of the non-standard GO7007 ioctls described -below. - - -The README files from the orignal package appear below: - ---------------------------------------------------------------------------- - WIS GO7007SB Public Linux Driver ---------------------------------------------------------------------------- - - -*** Please see the file RELEASE-NOTES for important last-minute updates *** - - - 0. OVERVIEW AND LICENSING/DISCLAIMER - - -This driver kit contains Linux drivers for the WIS GO7007SB multi-format -video encoder. Only kernel version 2.6.x is supported. The video stream -is available through the Video4Linux2 API and the audio stream is available -through the ALSA API (or the OSS emulation layer of the ALSA system). - -The files in kernel/ and hotplug/ are licensed under the GNU General Public -License Version 2 from the Free Software Foundation. A copy of the license -is included in the file COPYING. - -The example applications in apps/ and C header files in include/ are -licensed under a permissive license included in the source files which -allows copying, modification and redistribution for any purpose without -attribution. - -The firmware files included in the firmware/ directory may be freely -redistributed only in conjunction with this document; but modification, -tampering and reverse engineering are prohibited. - -MICRONAS USA, INC., MAKES NO WARRANTIES TO ANY PERSON OR ENTITY WITH -RESPECT TO THE SOFTWARE OR ANY DERIVATIVES THEREOF OR ANY SERVICES OR -LICENSES AND DISCLAIMS ALL IMPLIED WARRANTIES, INCLUDING WITHOUT LIMITATION -WARRANTIES OF MERCHANTABILITY, SUPPORT, AND FITNESS FOR A PARTICULAR -PURPOSE AND NON-INFRINGEMENT. - - - 1. SYSTEM REQUIREMENTS - - -This driver requires Linux kernel 2.6. Kernel 2.4 is not supported. Using -kernel 2.6.10 or later is recommended, as earlier kernels are known to have -unstable USB 2.0 support. - -A fully built kernel source tree must be available. Typically this will be -linked from "/lib/modules/<KERNEL VERSION>/build" for convenience. If this -link does not exist, an extra parameter will need to be passed to the -`make` command. - -All vendor-built kernels should already be configured properly. However, -for custom-built kernels, the following options need to be enabled in the -kernel as built-in or modules: - - CONFIG_MODULES - Enable loadable module support - CONFIG_FW_LOADER - Hotplug firmware loading support - CONFIG_I2C - I2C support - CONFIG_VIDEO_DEV - Video For Linux - CONFIG_SOUND - Sound card support - CONFIG_SND - Advanced Linux Sound Architecture - CONFIG_USB - Support for Host-side USB - CONFIG_USB_EHCI_HCD - EHCI HCD (USB 2.0) support - -Additionally, to use the example application, the following options need to -be enabled in the ALSA section: - - CONFIG_SND_MIXER_OSS - OSS Mixer API - CONFIG_SND_PCM_OSS - OSS PCM (digital audio) API - -The hotplug scripts, along with the fxload utility, must also be installed. -These scripts can be obtained from <http://linux-hotplug.sourceforge.net/>. -Hotplugging is used for loading firmware into the Cypruss EZ-USB chip using -fxload and for loading firmware into the driver using the firmware agent. - - - 2. COMPILING AND INSTALLING THE DRIVER - - -Most users should be able to compile the driver by simply running: - - $ make - -in the top-level directory of the driver kit. First the kernel modules -will be built, followed by the example applications. - -If the build system is unable to locate the kernel source tree for the -currently-running kernel, or if the module should be built for a kernel -other than the currently-running kernel, an additional parameter will need -to be passed to make to specify the appropriate kernel source directory: - - $ make KERNELSRC=/usr/src/linux-2.6.10-custom3 - -Once the compile completes, the driver and firmware files should be -installed by running: - - $ make install - -The kernel modules will be placed in "/lib/modules/<KERNEL VERSION>/extra" -and the firmware files will be placed in the appropriate hotplug firmware -directory, usually /lib/firmware. In addition, USB maps and scripts will -be placed in /etc/hotplug/usb to enable fxload to initialize the EZ-USB -control chip when the device is connected. - - - 3. PAL/SECAM TUNER CONFIGURATION (TV402U-EU only) - - -The PAL model of the Plextor ConvertX TV402U may require additional -configuration to correctly select the appropriate TV frequency band and -audio subchannel. - -Users with a device other than the Plextor ConvertX TV402U-EU should skip -this section. - -The wide variety of PAL TV systems used in Europe requires that additional -information about the local TV standards be passed to the driver in order -to properly tune TV channels. The two necessary parameters are (a) the PAL -TV band, and (b) the audio subchannel format in use. - -In many cases, the appropriate TV band selection is passed to the driver -from applications. However, in some cases, the application only specifies -that the driver should use PAL but not the specific information about the -appropriate TV band. To work around this issue, the correct TV band may be -specified in the "force_band" parameter to the wis-sony-tuner module: - - TV band force_band - ------- ---------- - PAL B/G B - PAL I I - PAL D/K D - SECAM L L - -If the "force_band" parameter is specified, the driver will ignore any TV -band specified by applications and will always use the band provided in the -module parameter. - -The other parameter that can be specified is the audio subchannel format. -There are several stereo audio carrier systems in use, including NICAM and -three varieties of A2. To receive audio broadcast on one of these stereo -carriers, the "force_mpx_mode" parameter must be specified to the -wis-sony-tuner module. - - TV band Audio subcarrier force_mpx_mode - ------- ---------------- -------------- - PAL B/G Mono (default) 1 - PAL B/G A2 2 - PAL B/G NICAM 3 - PAL I Mono (default) 4 - PAL I NICAM 5 - PAL D/K Mono (default) 6 - PAL D/K A2 (1) 7 - PAL D/K A2 (2) 8 - PAL D/K A2 (3) 9 - PAL D/K NICAM 10 - SECAM L Mono (default) 11 - SECAM L NICAM 12 - -If the "force_mpx_mode" parameter is not specified, the correct mono-only -mode will be chosen based on the TV band. However, the tuner will not -receive stereo audio or bilingual broadcasts correctly. - -To pass the "force_band" or "force_mpx_mode" parameters to the -wis-sony-tuner module, the following line must be added to the modprobe -configuration file, which varies from one Linux distribution to another. - - options wis-sony-tuner force_band=B force_mpx_mode=2 - -The above example would force the tuner to the PAL B/G TV band and receive -stereo audio broadcasts on the A2 carrier. - -To verify that the configuration has been placed in the correct location, -execute: - - $ modprobe -c | grep wis-sony-tuner - -If the configuration line appears, then modprobe will pass the parameters -correctly the next time the wis-sony-tuner module is loaded into the -kernel. - - - 4. TESTING THE DRIVER - - -Because few Linux applications are able to correctly capture from -Video4Linux2 devices with only compressed formats supported, the new driver -should be tested with the "gorecord" application in the apps/ directory. - -First connect a video source to the device, such as a DVD player or VCR. -This will be captured to a file for testing the driver. If an input source -is unavailable, a test file can still be captured, but the video will be -black and the audio will be silent. - -This application will auto-detect the V4L2 and ALSA/OSS device names of the -hardware and will record video and audio to an AVI file for a specified -number of seconds. For example: - - $ apps/gorecord -duration 60 capture.avi - -If this application does not successfully record an AVI file, the error -messages produced by gorecord and recorded in the system log (usually in -/var/log/messages) should provide information to help resolve the problem. - -Supplying no parameters to gorecord will cause it to probe the available -devices and exit. Use the -help flag for usage information. - - - 5. USING THE DRIVER - - -The V4L2 device implemented by the driver provides a standard compressed -format API, within the following criteria: - - * Applications that only support the original Video4Linux1 API will not - be able to communicate with this driver at all. - - * No raw video modes are supported, so applications like xawtv that - expect only uncompressed video will not function. - - * Supported compression formats are: Motion-JPEG, MPEG1, MPEG2 and MPEG4. - - * MPEG video formats are delivered as Video Elementary Streams only. - Program Stream (PS), Transport Stream (TS) and Packetized Elementary - Stream (PES) formats are not supported. - - * Video parameters such as format and input port may not be changed while - the encoder is active. - - * The audio capture device only functions when the video encoder is - actively capturing video. Attempts to read from the audio device when - the encoder is inactive will result in an I/O error. - - * The native format of the audio device is 48Khz 2-channel 16-bit - little-endian PCM, delivered through the ALSA system. No audio - compression is implemented in the hardware. ALSA may convert to other - uncompressed formats on the fly. - -The include/ directory contains a C header file describing non-standard -features of the GO7007SB encoder, which are described below: - - - GO7007IOC_S_COMP_PARAMS, GO7007IOC_G_COMP_PARAMS - - These ioctls are used to negotiate general compression parameters. - - To query the current parameters, call the GO7007IOC_G_COMP_PARAMS ioctl - with a pointer to a struct go7007_comp_params. If the driver is not - set to MPEG format, the EINVAL error code will be returned. - - To change the current parameters, initialize all fields of a struct - go7007_comp_params and call the GO7007_IOC_S_COMP_PARAMS ioctl with a - pointer to this structure. The driver will return the current - parameters with any necessary changes to conform to the limitations of - the hardware or current compression mode. Any or all fields can be set - to zero to request a reasonable default value. If the driver is not - set to MPEG format, the EINVAL error code will be returned. When I/O - is in progress, the EBUSY error code will be returned. - - Fields in struct go7007_comp_params: - - __u32 The maximum number of frames in each - gop_size Group Of Pictures; i.e. the maximum - number of frames minus one between - each key frame. - - __u32 The maximum number of sequential - max_b_frames bidirectionally-predicted frames. - (B-frames are not yet supported.) - - enum go7007_aspect_ratio The aspect ratio to be encoded in the - aspect_ratio meta-data of the compressed format. - - Choices are: - GO7007_ASPECT_RATIO_1_1 - GO7007_ASPECT_RATIO_4_3_NTSC - GO7007_ASPECT_RATIO_4_3_PAL - GO7007_ASPECT_RATIO_16_9_NTSC - GO7007_ASPECT_RATIO_16_9_PAL - - __u32 Bit-wise OR of control flags (below) - flags - - Flags in struct go7007_comp_params: - - GO7007_COMP_CLOSED_GOP Only produce self-contained GOPs, used - to produce streams appropriate for - random seeking. - - GO7007_COMP_OMIT_SEQ_HEADER Omit the stream sequence header. - - - GO7007IOC_S_MPEG_PARAMS, GO7007IOC_G_MPEG_PARAMS - - These ioctls are used to negotiate MPEG-specific stream parameters when - the pixelformat has been set to V4L2_PIX_FMT_MPEG. - - To query the current parameters, call the GO7007IOC_G_MPEG_PARAMS ioctl - with a pointer to a struct go7007_mpeg_params. If the driver is not - set to MPEG format, the EINVAL error code will be returned. - - To change the current parameters, initialize all fields of a struct - go7007_mpeg_params and call the GO7007_IOC_S_MPEG_PARAMS ioctl with a - pointer to this structure. The driver will return the current - parameters with any necessary changes to conform to the limitations of - the hardware or selected MPEG mode. Any or all fields can be set to - zero to request a reasonable default value. If the driver is not set - to MPEG format, the EINVAL error code will be returned. When I/O is in - progress, the EBUSY error code will be returned. - - Fields in struct go7007_mpeg_params: - - enum go7007_mpeg_video_standard - mpeg_video_standard The MPEG video standard in which to - compress the video. - - Choices are: - GO7007_MPEG_VIDEO_MPEG1 - GO7007_MPEG_VIDEO_MPEG2 - GO7007_MPEG_VIDEO_MPEG4 - - __u32 Bit-wise OR of control flags (below) - flags - - __u32 The profile and level indication to be - pali stored in the sequence header. This - is only used as an indicator to the - decoder, and does not affect the MPEG - features used in the video stream. - Not valid for MPEG1. - - Choices for MPEG2 are: - GO7007_MPEG2_PROFILE_MAIN_MAIN - - Choices for MPEG4 are: - GO7007_MPEG4_PROFILE_S_L0 - GO7007_MPEG4_PROFILE_S_L1 - GO7007_MPEG4_PROFILE_S_L2 - GO7007_MPEG4_PROFILE_S_L3 - GO7007_MPEG4_PROFILE_ARTS_L1 - GO7007_MPEG4_PROFILE_ARTS_L2 - GO7007_MPEG4_PROFILE_ARTS_L3 - GO7007_MPEG4_PROFILE_ARTS_L4 - GO7007_MPEG4_PROFILE_AS_L0 - GO7007_MPEG4_PROFILE_AS_L1 - GO7007_MPEG4_PROFILE_AS_L2 - GO7007_MPEG4_PROFILE_AS_L3 - GO7007_MPEG4_PROFILE_AS_L4 - GO7007_MPEG4_PROFILE_AS_L5 - - Flags in struct go7007_mpeg_params: - - GO7007_MPEG_FORCE_DVD_MODE Force all compression parameters and - bitrate control settings to comply - with DVD MPEG2 stream requirements. - This overrides most compression and - bitrate settings! - - GO7007_MPEG_OMIT_GOP_HEADER Omit the GOP header. - - GO7007_MPEG_REPEAT_SEQHEADER Repeat the MPEG sequence header at - the start of each GOP. - - - GO7007IOC_S_BITRATE, GO7007IOC_G_BITRATE - - These ioctls are used to set and query the target bitrate value for the - compressed video stream. The bitrate may be selected by storing the - target bits per second in an int and calling GO7007IOC_S_BITRATE with a - pointer to the int. The bitrate may be queried by calling - GO7007IOC_G_BITRATE with a pointer to an int where the current bitrate - will be stored. - - Note that this is the primary means of controlling the video quality - for all compression modes, including V4L2_PIX_FMT_MJPEG. The - VIDIOC_S_JPEGCOMP ioctl is not supported. - - ----------------------------------------------------------------------------- - Installing the WIS PCI Voyager Driver ---------------------------------------------------------------------------- - -The WIS PCI Voyager driver requires several patches to the Linux 2.6.11.x -kernel source tree before compiling the driver. These patches update the -in-kernel SAA7134 driver to the newest development version and patch bugs -in the TDA8290/TDA8275 tuner driver. - -The following patches must be downloaded from Gerd Knorr's website and -applied in the order listed: - - http://dl.bytesex.org/patches/2.6.11-2/i2c-tuner - http://dl.bytesex.org/patches/2.6.11-2/i2c-tuner2 - http://dl.bytesex.org/patches/2.6.11-2/v4l2-api-mpeg - http://dl.bytesex.org/patches/2.6.11-2/saa7134-update - -The following patches are included with this SDK and can be applied in any -order: - - patches/2.6.11/saa7134-voyager.diff - patches/2.6.11/tda8275-newaddr.diff - patches/2.6.11/tda8290-ntsc.diff - -Check to make sure the CONFIG_VIDEO_SAA7134 option is enabled in the kernel -configuration, and build and install the kernel. - -After rebooting into the new kernel, the GO7007 driver can be compiled and -installed: - - $ make SAA7134_BUILD=y - $ make install - $ modprobe saa7134-go7007 - -There will be two V4L video devices associated with the PCI Voyager. The -first device (most likely /dev/video0) provides access to the raw video -capture mode of the SAA7133 device and is used to configure the source -video parameters and tune the TV tuner. This device can be used with xawtv -or other V4L(2) video software as a standard uncompressed device. - -The second device (most likely /dev/video1) provides access to the -compression functions of the GO7007. It can be tested using the gorecord -application in the apps/ directory of this SDK: - - $ apps/gorecord -vdevice /dev/video1 -noaudio test.avi - -Currently the frame resolution is fixed at 720x480 (NTSC) or 720x576 (PAL), -and the video standard must be specified to both the raw and the compressed -video devices (xawtv and gorecord, for example). - - --------------------------------------------------------------------------- -RELEASE NOTES FOR WIS GO7007SB LINUX DRIVER ---------------------------------------------------------------------------- - -Last updated: 5 November 2005 - - - Release 0.9.7 includes new support for using udev to run fxload. The - install script should automatically detect whether the old hotplug - scripts or the new udev rules should be used. To force the use of - hotplug, run "make install USE_UDEV=n". To force the use of udev, run - "make install USE_UDEV=y". - - - Motion detection is supported but undocumented. Try the `modet` app - for a demonstration of how to use the facility. - - - Using USB2.0 devices such as the TV402U with USB1.1 HCDs or hubs can - cause buffer overruns and frame drops, even at low framerates, due to - inconsistency in the bitrate control mechanism. - - - On devices with an SAA7115, including the Plextor ConvertX, video height - values of 96, 128, 160, 192, 256, 320, and 384 do not work in NTSC mode. - All valid heights up to 512 work correctly in PAL mode. - - - The WIS Star Trek and PCI Voyager boards have no support yet for audio - or the TV tuner. diff --git a/drivers/staging/media/go7007/s2250-board.c b/drivers/staging/media/go7007/s2250-board.c deleted file mode 100644 index eaa2b0990a1b..000000000000 --- a/drivers/staging/media/go7007/s2250-board.c +++ /dev/null @@ -1,631 +0,0 @@ -/* - * Copyright (C) 2008 Sensoray Company Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * 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/usb.h> -#include <linux/i2c.h> -#include <linux/videodev2.h> -#include <linux/slab.h> -#include <media/v4l2-device.h> -#include <media/v4l2-common.h> -#include <media/v4l2-subdev.h> -#include "go7007-priv.h" - -MODULE_DESCRIPTION("Sensoray 2250/2251 i2c v4l2 subdev driver"); -MODULE_LICENSE("GPL v2"); - -/* - * Note: this board has two i2c devices: a vpx3226f and a tlv320aic23b. - * Due to the unusual way these are accessed on this device we do not - * reuse the i2c drivers, but instead they are implemented in this - * driver. It would be nice to improve on this, though. - */ - -#define TLV320_ADDRESS 0x34 -#define VPX322_ADDR_ANALOGCONTROL1 0x02 -#define VPX322_ADDR_BRIGHTNESS0 0x0127 -#define VPX322_ADDR_BRIGHTNESS1 0x0131 -#define VPX322_ADDR_CONTRAST0 0x0128 -#define VPX322_ADDR_CONTRAST1 0x0132 -#define VPX322_ADDR_HUE 0x00dc -#define VPX322_ADDR_SAT 0x0030 - -struct go7007_usb_board { - unsigned int flags; - struct go7007_board_info main_info; -}; - -struct go7007_usb { - struct go7007_usb_board *board; - struct mutex i2c_lock; - struct usb_device *usbdev; - struct urb *video_urbs[8]; - struct urb *audio_urbs[8]; - struct urb *intr_urb; -}; - -static unsigned char aud_regs[] = { - 0x1e, 0x00, - 0x00, 0x17, - 0x02, 0x17, - 0x04, 0xf9, - 0x06, 0xf9, - 0x08, 0x02, - 0x0a, 0x00, - 0x0c, 0x00, - 0x0a, 0x00, - 0x0c, 0x00, - 0x0e, 0x02, - 0x10, 0x00, - 0x12, 0x01, - 0x00, 0x00, -}; - - -static unsigned char vid_regs[] = { - 0xF2, 0x0f, - 0xAA, 0x00, - 0xF8, 0xff, - 0x00, 0x00, -}; - -static u16 vid_regs_fp[] = { - 0x028, 0x067, - 0x120, 0x016, - 0x121, 0xcF2, - 0x122, 0x0F2, - 0x123, 0x00c, - 0x124, 0x2d0, - 0x125, 0x2e0, - 0x126, 0x004, - 0x128, 0x1E0, - 0x12A, 0x016, - 0x12B, 0x0F2, - 0x12C, 0x0F2, - 0x12D, 0x00c, - 0x12E, 0x2d0, - 0x12F, 0x2e0, - 0x130, 0x004, - 0x132, 0x1E0, - 0x140, 0x060, - 0x153, 0x00C, - 0x154, 0x200, - 0x150, 0x801, - 0x000, 0x000 -}; - -/* PAL specific values */ -static u16 vid_regs_fp_pal[] = { - 0x120, 0x017, - 0x121, 0xd22, - 0x122, 0x122, - 0x12A, 0x017, - 0x12B, 0x122, - 0x12C, 0x122, - 0x140, 0x060, - 0x000, 0x000, -}; - -struct s2250 { - struct v4l2_subdev sd; - struct v4l2_ctrl_handler hdl; - v4l2_std_id std; - int input; - int brightness; - int contrast; - int saturation; - int hue; - int reg12b_val; - int audio_input; - struct i2c_client *audio; -}; - -static inline struct s2250 *to_state(struct v4l2_subdev *sd) -{ - return container_of(sd, struct s2250, sd); -} - -/* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/ -static int go7007_usb_vendor_request(struct go7007 *go, u16 request, - u16 value, u16 index, void *transfer_buffer, int length, int in) -{ - struct go7007_usb *usb = go->hpi_context; - int timeout = 5000; - - if (in) { - return usb_control_msg(usb->usbdev, - usb_rcvctrlpipe(usb->usbdev, 0), request, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - value, index, transfer_buffer, length, timeout); - } else { - return usb_control_msg(usb->usbdev, - usb_sndctrlpipe(usb->usbdev, 0), request, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, transfer_buffer, length, timeout); - } -} -/* end from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/ - -static int write_reg(struct i2c_client *client, u8 reg, u8 value) -{ - struct go7007 *go = i2c_get_adapdata(client->adapter); - struct go7007_usb *usb; - int rc; - int dev_addr = client->addr << 1; /* firmware wants 8-bit address */ - u8 *buf; - - if (go == NULL) - return -ENODEV; - - if (go->status == STATUS_SHUTDOWN) - return -EBUSY; - - buf = kzalloc(16, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - usb = go->hpi_context; - if (mutex_lock_interruptible(&usb->i2c_lock) != 0) { - dev_info(&client->dev, "i2c lock failed\n"); - kfree(buf); - return -EINTR; - } - rc = go7007_usb_vendor_request(go, 0x55, dev_addr, - (reg<<8 | value), - buf, - 16, 1); - - mutex_unlock(&usb->i2c_lock); - kfree(buf); - return rc; -} - -static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val) -{ - struct go7007 *go = i2c_get_adapdata(client->adapter); - struct go7007_usb *usb; - int rc; - u8 *buf; - struct s2250 *dec = i2c_get_clientdata(client); - - if (go == NULL) - return -ENODEV; - - if (go->status == STATUS_SHUTDOWN) - return -EBUSY; - - buf = kzalloc(16, GFP_KERNEL); - - if (buf == NULL) - return -ENOMEM; - - - - memset(buf, 0xcd, 6); - - usb = go->hpi_context; - if (mutex_lock_interruptible(&usb->i2c_lock) != 0) { - dev_info(&client->dev, "i2c lock failed\n"); - kfree(buf); - return -EINTR; - } - rc = go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1); - mutex_unlock(&usb->i2c_lock); - if (rc < 0) { - kfree(buf); - return rc; - } - - if (buf[0] == 0) { - unsigned int subaddr, val_read; - - subaddr = (buf[4] << 8) + buf[5]; - val_read = (buf[2] << 8) + buf[3]; - kfree(buf); - if (val_read != val) { - dev_info(&client->dev, "invalid fp write %x %x\n", - val_read, val); - return -EFAULT; - } - if (subaddr != addr) { - dev_info(&client->dev, "invalid fp write addr %x %x\n", - subaddr, addr); - return -EFAULT; - } - } else { - kfree(buf); - return -EFAULT; - } - - /* save last 12b value */ - if (addr == 0x12b) - dec->reg12b_val = val; - - return 0; -} - -static int read_reg_fp(struct i2c_client *client, u16 addr, u16 *val) -{ - struct go7007 *go = i2c_get_adapdata(client->adapter); - struct go7007_usb *usb; - int rc; - u8 *buf; - - if (go == NULL) - return -ENODEV; - - if (go->status == STATUS_SHUTDOWN) - return -EBUSY; - - buf = kzalloc(16, GFP_KERNEL); - - if (buf == NULL) - return -ENOMEM; - - - - memset(buf, 0xcd, 6); - usb = go->hpi_context; - if (mutex_lock_interruptible(&usb->i2c_lock) != 0) { - dev_info(&client->dev, "i2c lock failed\n"); - kfree(buf); - return -EINTR; - } - rc = go7007_usb_vendor_request(go, 0x58, addr, 0, buf, 16, 1); - mutex_unlock(&usb->i2c_lock); - if (rc < 0) { - kfree(buf); - return rc; - } - - *val = (buf[0] << 8) | buf[1]; - kfree(buf); - - return 0; -} - - -static int write_regs(struct i2c_client *client, u8 *regs) -{ - int i; - - for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) { - if (write_reg(client, regs[i], regs[i+1]) < 0) { - dev_info(&client->dev, "failed\n"); - return -1; - } - } - return 0; -} - -static int write_regs_fp(struct i2c_client *client, u16 *regs) -{ - int i; - - for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) { - if (write_reg_fp(client, regs[i], regs[i+1]) < 0) { - dev_info(&client->dev, "failed fp\n"); - return -1; - } - } - return 0; -} - - -/* ------------------------------------------------------------------------- */ - -static int s2250_s_video_routing(struct v4l2_subdev *sd, u32 input, u32 output, - u32 config) -{ - struct s2250 *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - int vidsys; - - vidsys = (state->std == V4L2_STD_NTSC) ? 0x01 : 0x00; - if (input == 0) { - /* composite */ - write_reg_fp(client, 0x20, 0x020 | vidsys); - write_reg_fp(client, 0x21, 0x662); - write_reg_fp(client, 0x140, 0x060); - } else if (input == 1) { - /* S-Video */ - write_reg_fp(client, 0x20, 0x040 | vidsys); - write_reg_fp(client, 0x21, 0x666); - write_reg_fp(client, 0x140, 0x060); - } else { - return -EINVAL; - } - state->input = input; - return 0; -} - -static int s2250_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) -{ - struct s2250 *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - u16 vidsource; - - vidsource = (state->input == 1) ? 0x040 : 0x020; - if (norm & V4L2_STD_625_50) { - write_regs_fp(client, vid_regs_fp); - write_regs_fp(client, vid_regs_fp_pal); - write_reg_fp(client, 0x20, vidsource); - } else { - write_regs_fp(client, vid_regs_fp); - write_reg_fp(client, 0x20, vidsource | 1); - } - state->std = norm; - return 0; -} - -static int s2250_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct s2250 *state = container_of(ctrl->handler, struct s2250, hdl); - struct i2c_client *client = v4l2_get_subdevdata(&state->sd); - u16 oldvalue; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue); - write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, - ctrl->val | (oldvalue & ~0xff)); - read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue); - write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, - ctrl->val | (oldvalue & ~0xff)); - write_reg_fp(client, 0x140, 0x60); - break; - case V4L2_CID_CONTRAST: - read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue); - write_reg_fp(client, VPX322_ADDR_CONTRAST0, - ctrl->val | (oldvalue & ~0x3f)); - read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue); - write_reg_fp(client, VPX322_ADDR_CONTRAST1, - ctrl->val | (oldvalue & ~0x3f)); - write_reg_fp(client, 0x140, 0x60); - break; - case V4L2_CID_SATURATION: - write_reg_fp(client, VPX322_ADDR_SAT, ctrl->val); - break; - case V4L2_CID_HUE: - write_reg_fp(client, VPX322_ADDR_HUE, ctrl->val); - break; - default: - return -EINVAL; - } - return 0; -} - -static int s2250_s_mbus_fmt(struct v4l2_subdev *sd, - struct v4l2_mbus_framefmt *fmt) -{ - struct s2250 *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (fmt->height < 640) { - write_reg_fp(client, 0x12b, state->reg12b_val | 0x400); - write_reg_fp(client, 0x140, 0x060); - } else { - write_reg_fp(client, 0x12b, state->reg12b_val & ~0x400); - write_reg_fp(client, 0x140, 0x060); - } - return 0; -} - -static int s2250_s_audio_routing(struct v4l2_subdev *sd, u32 input, u32 output, - u32 config) -{ - struct s2250 *state = to_state(sd); - - switch (input) { - case 0: - write_reg(state->audio, 0x08, 0x02); /* Line In */ - break; - case 1: - write_reg(state->audio, 0x08, 0x04); /* Mic */ - break; - case 2: - write_reg(state->audio, 0x08, 0x05); /* Mic Boost */ - break; - default: - return -EINVAL; - } - state->audio_input = input; - return 0; -} - - -static int s2250_log_status(struct v4l2_subdev *sd) -{ - struct s2250 *state = to_state(sd); - - v4l2_info(sd, "Standard: %s\n", state->std == V4L2_STD_NTSC ? "NTSC" : - state->std == V4L2_STD_PAL ? "PAL" : - state->std == V4L2_STD_SECAM ? "SECAM" : - "unknown"); - v4l2_info(sd, "Input: %s\n", state->input == 0 ? "Composite" : - state->input == 1 ? "S-video" : - "error"); - v4l2_info(sd, "Audio input: %s\n", state->audio_input == 0 ? "Line In" : - state->audio_input == 1 ? "Mic" : - state->audio_input == 2 ? "Mic Boost" : - "error"); - return v4l2_ctrl_subdev_log_status(sd); -} - -/* --------------------------------------------------------------------------*/ - -static const struct v4l2_ctrl_ops s2250_ctrl_ops = { - .s_ctrl = s2250_s_ctrl, -}; - -static const struct v4l2_subdev_core_ops s2250_core_ops = { - .log_status = s2250_log_status, -}; - -static const struct v4l2_subdev_audio_ops s2250_audio_ops = { - .s_routing = s2250_s_audio_routing, -}; - -static const struct v4l2_subdev_video_ops s2250_video_ops = { - .s_std = s2250_s_std, - .s_routing = s2250_s_video_routing, - .s_mbus_fmt = s2250_s_mbus_fmt, -}; - -static const struct v4l2_subdev_ops s2250_ops = { - .core = &s2250_core_ops, - .audio = &s2250_audio_ops, - .video = &s2250_video_ops, -}; - -/* --------------------------------------------------------------------------*/ - -static int s2250_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_client *audio; - struct i2c_adapter *adapter = client->adapter; - struct s2250 *state; - struct v4l2_subdev *sd; - u8 *data; - struct go7007 *go = i2c_get_adapdata(adapter); - struct go7007_usb *usb = go->hpi_context; - - audio = i2c_new_dummy(adapter, TLV320_ADDRESS >> 1); - if (audio == NULL) - return -ENOMEM; - - state = kzalloc(sizeof(struct s2250), GFP_KERNEL); - if (state == NULL) { - i2c_unregister_device(audio); - return -ENOMEM; - } - - sd = &state->sd; - v4l2_i2c_subdev_init(sd, client, &s2250_ops); - - v4l2_info(sd, "initializing %s at address 0x%x on %s\n", - "Sensoray 2250/2251", client->addr, client->adapter->name); - - v4l2_ctrl_handler_init(&state->hdl, 4); - v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops, - V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); - v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops, - V4L2_CID_CONTRAST, 0, 0x3f, 1, 0x32); - v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops, - V4L2_CID_SATURATION, 0, 4094, 1, 2070); - v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops, - V4L2_CID_HUE, -512, 511, 1, 0); - sd->ctrl_handler = &state->hdl; - if (state->hdl.error) { - int err = state->hdl.error; - - v4l2_ctrl_handler_free(&state->hdl); - kfree(state); - return err; - } - - state->std = V4L2_STD_NTSC; - state->brightness = 50; - state->contrast = 50; - state->saturation = 50; - state->hue = 0; - state->audio = audio; - - /* initialize the audio */ - if (write_regs(audio, aud_regs) < 0) { - dev_err(&client->dev, "error initializing audio\n"); - goto fail; - } - - if (write_regs(client, vid_regs) < 0) { - dev_err(&client->dev, "error initializing decoder\n"); - goto fail; - } - if (write_regs_fp(client, vid_regs_fp) < 0) { - dev_err(&client->dev, "error initializing decoder\n"); - goto fail; - } - /* set default channel */ - /* composite */ - write_reg_fp(client, 0x20, 0x020 | 1); - write_reg_fp(client, 0x21, 0x662); - write_reg_fp(client, 0x140, 0x060); - - /* set default audio input */ - state->audio_input = 0; - write_reg(client, 0x08, 0x02); /* Line In */ - - if (mutex_lock_interruptible(&usb->i2c_lock) == 0) { - data = kzalloc(16, GFP_KERNEL); - if (data != NULL) { - int rc; - rc = go7007_usb_vendor_request(go, 0x41, 0, 0, - data, 16, 1); - if (rc > 0) { - u8 mask; - data[0] = 0; - mask = 1<<5; - data[0] &= ~mask; - data[1] |= mask; - go7007_usb_vendor_request(go, 0x40, 0, - (data[1]<<8) - + data[1], - data, 16, 0); - } - kfree(data); - } - mutex_unlock(&usb->i2c_lock); - } - - v4l2_info(sd, "initialized successfully\n"); - return 0; - -fail: - i2c_unregister_device(audio); - v4l2_ctrl_handler_free(&state->hdl); - kfree(state); - return -EIO; -} - -static int s2250_remove(struct i2c_client *client) -{ - struct s2250 *state = to_state(i2c_get_clientdata(client)); - - v4l2_device_unregister_subdev(&state->sd); - v4l2_ctrl_handler_free(&state->hdl); - kfree(state); - return 0; -} - -static const struct i2c_device_id s2250_id[] = { - { "s2250", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, s2250_id); - -static struct i2c_driver s2250_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "s2250", - }, - .probe = s2250_probe, - .remove = s2250_remove, - .id_table = s2250_id, -}; - -module_i2c_driver(s2250_driver); diff --git a/drivers/staging/media/go7007/saa7134-go7007.c b/drivers/staging/media/go7007/saa7134-go7007.c deleted file mode 100644 index e40f7fbfc0a5..000000000000 --- a/drivers/staging/media/go7007/saa7134-go7007.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Copyright (C) 2005-2006 Micronas USA Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * 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/init.h> -#include <linux/spinlock.h> -#include <linux/wait.h> -#include <linux/list.h> -#include <linux/slab.h> -#include <linux/time.h> -#include <linux/mm.h> -#include <linux/usb.h> -#include <linux/i2c.h> -#include <asm/byteorder.h> -#include <media/v4l2-common.h> -#include <media/v4l2-device.h> -#include <media/v4l2-subdev.h> - -#include "saa7134.h" -#include "saa7134-reg.h" -#include "go7007.h" -#include "go7007-priv.h" - -/*#define GO7007_HPI_DEBUG*/ - -enum hpi_address { - HPI_ADDR_VIDEO_BUFFER = 0xe4, - HPI_ADDR_INIT_BUFFER = 0xea, - HPI_ADDR_INTR_RET_VALUE = 0xee, - HPI_ADDR_INTR_RET_DATA = 0xec, - HPI_ADDR_INTR_STATUS = 0xf4, - HPI_ADDR_INTR_WR_PARAM = 0xf6, - HPI_ADDR_INTR_WR_INDEX = 0xf8, -}; - -enum gpio_command { - GPIO_COMMAND_RESET = 0x00, /* 000b */ - GPIO_COMMAND_REQ1 = 0x04, /* 001b */ - GPIO_COMMAND_WRITE = 0x20, /* 010b */ - GPIO_COMMAND_REQ2 = 0x24, /* 011b */ - GPIO_COMMAND_READ = 0x80, /* 100b */ - GPIO_COMMAND_VIDEO = 0x84, /* 101b */ - GPIO_COMMAND_IDLE = 0xA0, /* 110b */ - GPIO_COMMAND_ADDR = 0xA4, /* 111b */ -}; - -struct saa7134_go7007 { - struct v4l2_subdev sd; - struct saa7134_dev *dev; - u8 *top; - u8 *bottom; - dma_addr_t top_dma; - dma_addr_t bottom_dma; -}; - -static inline struct saa7134_go7007 *to_state(struct v4l2_subdev *sd) -{ - return container_of(sd, struct saa7134_go7007, sd); -} - -static const struct go7007_board_info board_voyager = { - .flags = 0, - .sensor_flags = GO7007_SENSOR_656 | - GO7007_SENSOR_VALID_ENABLE | - GO7007_SENSOR_TV | - GO7007_SENSOR_VBI, - .audio_flags = GO7007_AUDIO_I2S_MODE_1 | - GO7007_AUDIO_WORD_16, - .audio_rate = 48000, - .audio_bclk_div = 8, - .audio_main_div = 2, - .hpi_buffer_cap = 7, - .num_inputs = 1, - .inputs = { - { - .name = "SAA7134", - }, - }, -}; - -/********************* Driver for GPIO HPI interface *********************/ - -static int gpio_write(struct saa7134_dev *dev, u8 addr, u16 data) -{ - saa_writeb(SAA7134_GPIO_GPMODE0, 0xff); - - /* Write HPI address */ - saa_writeb(SAA7134_GPIO_GPSTATUS0, addr); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); - - /* Write low byte */ - saa_writeb(SAA7134_GPIO_GPSTATUS0, data & 0xff); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); - - /* Write high byte */ - saa_writeb(SAA7134_GPIO_GPSTATUS0, data >> 8); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); - - return 0; -} - -static int gpio_read(struct saa7134_dev *dev, u8 addr, u16 *data) -{ - saa_writeb(SAA7134_GPIO_GPMODE0, 0xff); - - /* Write HPI address */ - saa_writeb(SAA7134_GPIO_GPSTATUS0, addr); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); - - saa_writeb(SAA7134_GPIO_GPMODE0, 0x00); - - /* Read low byte */ - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_READ); - saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - *data = saa_readb(SAA7134_GPIO_GPSTATUS0); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); - - /* Read high byte */ - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_READ); - saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - *data |= saa_readb(SAA7134_GPIO_GPSTATUS0) << 8; - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); - - return 0; -} - -static int saa7134_go7007_interface_reset(struct go7007 *go) -{ - struct saa7134_go7007 *saa = go->hpi_context; - struct saa7134_dev *dev = saa->dev; - u32 status; - u16 intr_val, intr_data; - int count = 20; - - saa_clearb(SAA7134_TS_PARALLEL, 0x80); /* Disable TS interface */ - saa_writeb(SAA7134_GPIO_GPMODE2, 0xa4); - saa_writeb(SAA7134_GPIO_GPMODE0, 0xff); - - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_RESET); - msleep(1); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ2); - msleep(10); - - saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - - status = saa_readb(SAA7134_GPIO_GPSTATUS2); - /*printk(KERN_DEBUG "status is %s\n", status & 0x40 ? "OK" : "not OK"); */ - - /* enter command mode...(?) */ - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ2); - - do { - saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - status = saa_readb(SAA7134_GPIO_GPSTATUS2); - /*printk(KERN_INFO "gpio is %08x\n", saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)); */ - } while (--count > 0); - - /* Wait for an interrupt to indicate successful hardware reset */ - if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || - (intr_val & ~0x1) != 0x55aa) { - printk(KERN_ERR - "saa7134-go7007: unable to reset the GO7007\n"); - return -1; - } - return 0; -} - -static int saa7134_go7007_write_interrupt(struct go7007 *go, int addr, int data) -{ - struct saa7134_go7007 *saa = go->hpi_context; - struct saa7134_dev *dev = saa->dev; - int i; - u16 status_reg; - -#ifdef GO7007_HPI_DEBUG - printk(KERN_DEBUG - "saa7134-go7007: WriteInterrupt: %04x %04x\n", addr, data); -#endif - - for (i = 0; i < 100; ++i) { - gpio_read(dev, HPI_ADDR_INTR_STATUS, &status_reg); - if (!(status_reg & 0x0010)) - break; - msleep(10); - } - if (i == 100) { - printk(KERN_ERR - "saa7134-go7007: device is hung, status reg = 0x%04x\n", - status_reg); - return -1; - } - gpio_write(dev, HPI_ADDR_INTR_WR_PARAM, data); - gpio_write(dev, HPI_ADDR_INTR_WR_INDEX, addr); - - return 0; -} - -static int saa7134_go7007_read_interrupt(struct go7007 *go) -{ - struct saa7134_go7007 *saa = go->hpi_context; - struct saa7134_dev *dev = saa->dev; - - /* XXX we need to wait if there is no interrupt available */ - go->interrupt_available = 1; - gpio_read(dev, HPI_ADDR_INTR_RET_VALUE, &go->interrupt_value); - gpio_read(dev, HPI_ADDR_INTR_RET_DATA, &go->interrupt_data); -#ifdef GO7007_HPI_DEBUG - printk(KERN_DEBUG "saa7134-go7007: ReadInterrupt: %04x %04x\n", - go->interrupt_value, go->interrupt_data); -#endif - return 0; -} - -static void saa7134_go7007_irq_ts_done(struct saa7134_dev *dev, - unsigned long status) -{ - struct go7007 *go = video_get_drvdata(dev->empress_dev); - struct saa7134_go7007 *saa = go->hpi_context; - - if (!vb2_is_streaming(&go->vidq)) - return; - if (0 != (status & 0x000f0000)) - printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n", - (status >> 16) & 0x0f); - if (status & 0x100000) { - dma_sync_single_for_cpu(&dev->pci->dev, - saa->bottom_dma, PAGE_SIZE, DMA_FROM_DEVICE); - go7007_parse_video_stream(go, saa->bottom, PAGE_SIZE); - saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma)); - } else { - dma_sync_single_for_cpu(&dev->pci->dev, - saa->top_dma, PAGE_SIZE, DMA_FROM_DEVICE); - go7007_parse_video_stream(go, saa->top, PAGE_SIZE); - saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma)); - } -} - -static int saa7134_go7007_stream_start(struct go7007 *go) -{ - struct saa7134_go7007 *saa = go->hpi_context; - struct saa7134_dev *dev = saa->dev; - - saa->top_dma = dma_map_page(&dev->pci->dev, virt_to_page(saa->top), - 0, PAGE_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(&dev->pci->dev, saa->top_dma)) - return -ENOMEM; - saa->bottom_dma = dma_map_page(&dev->pci->dev, - virt_to_page(saa->bottom), - 0, PAGE_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(&dev->pci->dev, saa->bottom_dma)) { - dma_unmap_page(&dev->pci->dev, saa->top_dma, PAGE_SIZE, - DMA_FROM_DEVICE); - return -ENOMEM; - } - - saa_writel(SAA7134_VIDEO_PORT_CTRL0 >> 2, 0xA300B000); - saa_writel(SAA7134_VIDEO_PORT_CTRL4 >> 2, 0x40000200); - - /* Set HPI interface for video */ - saa_writeb(SAA7134_GPIO_GPMODE0, 0xff); - saa_writeb(SAA7134_GPIO_GPSTATUS0, HPI_ADDR_VIDEO_BUFFER); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR); - saa_writeb(SAA7134_GPIO_GPMODE0, 0x00); - - /* Enable TS interface */ - saa_writeb(SAA7134_TS_PARALLEL, 0xe6); - - /* Reset TS interface */ - saa_setb(SAA7134_TS_SERIAL1, 0x01); - saa_clearb(SAA7134_TS_SERIAL1, 0x01); - - /* Set up transfer block size */ - saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 128 - 1); - saa_writeb(SAA7134_TS_DMA0, (PAGE_SIZE >> 7) - 1); - saa_writeb(SAA7134_TS_DMA1, 0); - saa_writeb(SAA7134_TS_DMA2, 0); - - /* Enable video streaming mode */ - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_VIDEO); - - saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma)); - saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma)); - saa_writel(SAA7134_RS_PITCH(5), 128); - saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_MAX); - - /* Enable TS FIFO */ - saa_setl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE5); - - /* Enable DMA IRQ */ - saa_setl(SAA7134_IRQ1, - SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0); - - return 0; -} - -static int saa7134_go7007_stream_stop(struct go7007 *go) -{ - struct saa7134_go7007 *saa = go->hpi_context; - struct saa7134_dev *dev; - - if (!saa) - return -EINVAL; - dev = saa->dev; - if (!dev) - return -EINVAL; - - /* Shut down TS FIFO */ - saa_clearl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE5); - - /* Disable DMA IRQ */ - saa_clearl(SAA7134_IRQ1, - SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0); - - /* Disable TS interface */ - saa_clearb(SAA7134_TS_PARALLEL, 0x80); - - dma_unmap_page(&dev->pci->dev, saa->top_dma, PAGE_SIZE, - DMA_FROM_DEVICE); - dma_unmap_page(&dev->pci->dev, saa->bottom_dma, PAGE_SIZE, - DMA_FROM_DEVICE); - - return 0; -} - -static int saa7134_go7007_send_firmware(struct go7007 *go, u8 *data, int len) -{ - struct saa7134_go7007 *saa = go->hpi_context; - struct saa7134_dev *dev = saa->dev; - u16 status_reg; - int i; - -#ifdef GO7007_HPI_DEBUG - printk(KERN_DEBUG "saa7134-go7007: DownloadBuffer " - "sending %d bytes\n", len); -#endif - - while (len > 0) { - i = len > 64 ? 64 : len; - saa_writeb(SAA7134_GPIO_GPMODE0, 0xff); - saa_writeb(SAA7134_GPIO_GPSTATUS0, HPI_ADDR_INIT_BUFFER); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); - while (i-- > 0) { - saa_writeb(SAA7134_GPIO_GPSTATUS0, *data); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE); - saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); - ++data; - --len; - } - for (i = 0; i < 100; ++i) { - gpio_read(dev, HPI_ADDR_INTR_STATUS, &status_reg); - if (!(status_reg & 0x0002)) - break; - } - if (i == 100) { - printk(KERN_ERR "saa7134-go7007: device is hung, " - "status reg = 0x%04x\n", status_reg); - return -1; - } - } - return 0; -} - -static struct go7007_hpi_ops saa7134_go7007_hpi_ops = { - .interface_reset = saa7134_go7007_interface_reset, - .write_interrupt = saa7134_go7007_write_interrupt, - .read_interrupt = saa7134_go7007_read_interrupt, - .stream_start = saa7134_go7007_stream_start, - .stream_stop = saa7134_go7007_stream_stop, - .send_firmware = saa7134_go7007_send_firmware, -}; -MODULE_FIRMWARE("go7007/go7007tv.bin"); - -/* --------------------------------------------------------------------------*/ - -static int saa7134_go7007_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) -{ - struct saa7134_go7007 *saa = to_state(sd); - struct saa7134_dev *dev = saa->dev; - - return saa7134_s_std_internal(dev, NULL, norm); -} - -static int saa7134_go7007_queryctrl(struct v4l2_subdev *sd, - struct v4l2_queryctrl *query) -{ - return saa7134_queryctrl(NULL, NULL, query); -} -static int saa7134_go7007_s_ctrl(struct v4l2_subdev *sd, - struct v4l2_control *ctrl) -{ - struct saa7134_go7007 *saa = to_state(sd); - struct saa7134_dev *dev = saa->dev; - return saa7134_s_ctrl_internal(dev, NULL, ctrl); -} - -static int saa7134_go7007_g_ctrl(struct v4l2_subdev *sd, - struct v4l2_control *ctrl) -{ - struct saa7134_go7007 *saa = to_state(sd); - struct saa7134_dev *dev = saa->dev; - return saa7134_g_ctrl_internal(dev, NULL, ctrl); -} - -/* --------------------------------------------------------------------------*/ - -static const struct v4l2_subdev_core_ops saa7134_go7007_core_ops = { - .g_ctrl = saa7134_go7007_g_ctrl, - .s_ctrl = saa7134_go7007_s_ctrl, - .queryctrl = saa7134_go7007_queryctrl, -}; - -static const struct v4l2_subdev_video_ops saa7134_go7007_video_ops = { - .s_std = saa7134_go7007_s_std, -}; - -static const struct v4l2_subdev_ops saa7134_go7007_sd_ops = { - .core = &saa7134_go7007_core_ops, - .video = &saa7134_go7007_video_ops, -}; - -/* --------------------------------------------------------------------------*/ - - -/********************* Add/remove functions *********************/ - -static int saa7134_go7007_init(struct saa7134_dev *dev) -{ - struct go7007 *go; - struct saa7134_go7007 *saa; - struct v4l2_subdev *sd; - - printk(KERN_DEBUG "saa7134-go7007: probing new SAA713X board\n"); - - go = go7007_alloc(&board_voyager, &dev->pci->dev); - if (go == NULL) - return -ENOMEM; - - saa = kzalloc(sizeof(struct saa7134_go7007), GFP_KERNEL); - if (saa == NULL) { - kfree(go); - return -ENOMEM; - } - - go->board_id = GO7007_BOARDID_PCI_VOYAGER; - snprintf(go->bus_info, sizeof(go->bus_info), "PCI:%s", pci_name(dev->pci)); - strlcpy(go->name, saa7134_boards[dev->board].name, sizeof(go->name)); - go->hpi_ops = &saa7134_go7007_hpi_ops; - go->hpi_context = saa; - saa->dev = dev; - - /* Init the subdevice interface */ - sd = &saa->sd; - v4l2_subdev_init(sd, &saa7134_go7007_sd_ops); - v4l2_set_subdevdata(sd, saa); - strncpy(sd->name, "saa7134-go7007", sizeof(sd->name)); - - /* Allocate a couple pages for receiving the compressed stream */ - saa->top = (u8 *)get_zeroed_page(GFP_KERNEL); - if (!saa->top) - goto allocfail; - saa->bottom = (u8 *)get_zeroed_page(GFP_KERNEL); - if (!saa->bottom) - goto allocfail; - - /* Boot the GO7007 */ - if (go7007_boot_encoder(go, go->board_info->flags & - GO7007_BOARD_USE_ONBOARD_I2C) < 0) - goto allocfail; - - /* Do any final GO7007 initialization, then register the - * V4L2 and ALSA interfaces */ - if (go7007_register_encoder(go, go->board_info->num_i2c_devs) < 0) - goto allocfail; - - /* Register the subdevice interface with the go7007 device */ - if (v4l2_device_register_subdev(&go->v4l2_dev, sd) < 0) - printk(KERN_INFO "saa7134-go7007: register subdev failed\n"); - - dev->empress_dev = &go->vdev; - - go->status = STATUS_ONLINE; - return 0; - -allocfail: - if (saa->top) - free_page((unsigned long)saa->top); - if (saa->bottom) - free_page((unsigned long)saa->bottom); - kfree(saa); - kfree(go); - return -ENOMEM; -} - -static int saa7134_go7007_fini(struct saa7134_dev *dev) -{ - struct go7007 *go; - struct saa7134_go7007 *saa; - - if (NULL == dev->empress_dev) - return 0; - - go = video_get_drvdata(dev->empress_dev); - if (go->audio_enabled) - go7007_snd_remove(go); - - saa = go->hpi_context; - go->status = STATUS_SHUTDOWN; - free_page((unsigned long)saa->top); - free_page((unsigned long)saa->bottom); - v4l2_device_unregister_subdev(&saa->sd); - kfree(saa); - video_unregister_device(&go->vdev); - - v4l2_device_put(&go->v4l2_dev); - dev->empress_dev = NULL; - - return 0; -} - -static struct saa7134_mpeg_ops saa7134_go7007_ops = { - .type = SAA7134_MPEG_GO7007, - .init = saa7134_go7007_init, - .fini = saa7134_go7007_fini, - .irq_ts_done = saa7134_go7007_irq_ts_done, -}; - -static int __init saa7134_go7007_mod_init(void) -{ - return saa7134_ts_register(&saa7134_go7007_ops); -} - -static void __exit saa7134_go7007_mod_cleanup(void) -{ - saa7134_ts_unregister(&saa7134_go7007_ops); -} - -module_init(saa7134_go7007_mod_init); -module_exit(saa7134_go7007_mod_cleanup); - -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/media/go7007/snd-go7007.c b/drivers/staging/media/go7007/snd-go7007.c deleted file mode 100644 index 9eb2a20ae40a..000000000000 --- a/drivers/staging/media/go7007/snd-go7007.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) 2005-2006 Micronas USA Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * 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/kernel.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/spinlock.h> -#include <linux/delay.h> -#include <linux/sched.h> -#include <linux/vmalloc.h> -#include <linux/time.h> -#include <linux/mm.h> -#include <linux/i2c.h> -#include <linux/mutex.h> -#include <linux/uaccess.h> -#include <linux/slab.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/initval.h> - -#include "go7007-priv.h" - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -module_param_array(id, charp, NULL, 0444); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the go7007 audio driver"); -MODULE_PARM_DESC(id, "ID string for the go7007 audio driver"); -MODULE_PARM_DESC(enable, "Enable for the go7007 audio driver"); - -struct go7007_snd { - struct snd_card *card; - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - spinlock_t lock; - int w_idx; - int hw_ptr; - int avail; - int capturing; -}; - -static struct snd_pcm_hardware go7007_snd_capture_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 4096, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 32, -}; - -static void parse_audio_stream_data(struct go7007 *go, u8 *buf, int length) -{ - struct go7007_snd *gosnd = go->snd_context; - struct snd_pcm_runtime *runtime = gosnd->substream->runtime; - int frames = bytes_to_frames(runtime, length); - - spin_lock(&gosnd->lock); - gosnd->hw_ptr += frames; - if (gosnd->hw_ptr >= runtime->buffer_size) - gosnd->hw_ptr -= runtime->buffer_size; - gosnd->avail += frames; - spin_unlock(&gosnd->lock); - if (gosnd->w_idx + length > runtime->dma_bytes) { - int cpy = runtime->dma_bytes - gosnd->w_idx; - - memcpy(runtime->dma_area + gosnd->w_idx, buf, cpy); - length -= cpy; - buf += cpy; - gosnd->w_idx = 0; - } - memcpy(runtime->dma_area + gosnd->w_idx, buf, length); - gosnd->w_idx += length; - spin_lock(&gosnd->lock); - if (gosnd->avail < runtime->period_size) { - spin_unlock(&gosnd->lock); - return; - } - gosnd->avail -= runtime->period_size; - spin_unlock(&gosnd->lock); - if (gosnd->capturing) - snd_pcm_period_elapsed(gosnd->substream); -} - -static int go7007_snd_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct go7007 *go = snd_pcm_substream_chip(substream); - unsigned int bytes; - - bytes = params_buffer_bytes(hw_params); - if (substream->runtime->dma_bytes > 0) - vfree(substream->runtime->dma_area); - substream->runtime->dma_bytes = 0; - substream->runtime->dma_area = vmalloc(bytes); - if (substream->runtime->dma_area == NULL) - return -ENOMEM; - substream->runtime->dma_bytes = bytes; - go->audio_deliver = parse_audio_stream_data; - return 0; -} - -static int go7007_snd_hw_free(struct snd_pcm_substream *substream) -{ - struct go7007 *go = snd_pcm_substream_chip(substream); - - go->audio_deliver = NULL; - if (substream->runtime->dma_bytes > 0) - vfree(substream->runtime->dma_area); - substream->runtime->dma_bytes = 0; - return 0; -} - -static int go7007_snd_capture_open(struct snd_pcm_substream *substream) -{ - struct go7007 *go = snd_pcm_substream_chip(substream); - struct go7007_snd *gosnd = go->snd_context; - unsigned long flags; - int r; - - spin_lock_irqsave(&gosnd->lock, flags); - if (gosnd->substream == NULL) { - gosnd->substream = substream; - substream->runtime->hw = go7007_snd_capture_hw; - r = 0; - } else - r = -EBUSY; - spin_unlock_irqrestore(&gosnd->lock, flags); - return r; -} - -static int go7007_snd_capture_close(struct snd_pcm_substream *substream) -{ - struct go7007 *go = snd_pcm_substream_chip(substream); - struct go7007_snd *gosnd = go->snd_context; - - gosnd->substream = NULL; - return 0; -} - -static int go7007_snd_pcm_prepare(struct snd_pcm_substream *substream) -{ - return 0; -} - -static int go7007_snd_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct go7007 *go = snd_pcm_substream_chip(substream); - struct go7007_snd *gosnd = go->snd_context; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* Just set a flag to indicate we should signal ALSA when - * sound comes in */ - gosnd->capturing = 1; - return 0; - case SNDRV_PCM_TRIGGER_STOP: - gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0; - gosnd->capturing = 0; - return 0; - default: - return -EINVAL; - } -} - -static snd_pcm_uframes_t go7007_snd_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct go7007 *go = snd_pcm_substream_chip(substream); - struct go7007_snd *gosnd = go->snd_context; - - return gosnd->hw_ptr; -} - -static struct page *go7007_snd_pcm_page(struct snd_pcm_substream *substream, - unsigned long offset) -{ - return vmalloc_to_page(substream->runtime->dma_area + offset); -} - -static struct snd_pcm_ops go7007_snd_capture_ops = { - .open = go7007_snd_capture_open, - .close = go7007_snd_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = go7007_snd_hw_params, - .hw_free = go7007_snd_hw_free, - .prepare = go7007_snd_pcm_prepare, - .trigger = go7007_snd_pcm_trigger, - .pointer = go7007_snd_pcm_pointer, - .page = go7007_snd_pcm_page, -}; - -static int go7007_snd_free(struct snd_device *device) -{ - struct go7007 *go = device->device_data; - - kfree(go->snd_context); - go->snd_context = NULL; - return 0; -} - -static struct snd_device_ops go7007_snd_device_ops = { - .dev_free = go7007_snd_free, -}; - -int go7007_snd_init(struct go7007 *go) -{ - static int dev; - struct go7007_snd *gosnd; - int ret = 0; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - gosnd = kmalloc(sizeof(struct go7007_snd), GFP_KERNEL); - if (gosnd == NULL) - return -ENOMEM; - spin_lock_init(&gosnd->lock); - gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0; - gosnd->capturing = 0; - ret = snd_card_new(go->dev, index[dev], id[dev], THIS_MODULE, 0, - &gosnd->card); - if (ret < 0) { - kfree(gosnd); - return ret; - } - ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go, - &go7007_snd_device_ops); - if (ret < 0) { - kfree(gosnd); - return ret; - } - ret = snd_pcm_new(gosnd->card, "go7007", 0, 0, 1, &gosnd->pcm); - if (ret < 0) { - snd_card_free(gosnd->card); - kfree(gosnd); - return ret; - } - strlcpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver)); - strlcpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver)); - strlcpy(gosnd->card->longname, gosnd->card->shortname, - sizeof(gosnd->card->longname)); - - gosnd->pcm->private_data = go; - snd_pcm_set_ops(gosnd->pcm, SNDRV_PCM_STREAM_CAPTURE, - &go7007_snd_capture_ops); - - ret = snd_card_register(gosnd->card); - if (ret < 0) { - snd_card_free(gosnd->card); - kfree(gosnd); - return ret; - } - - gosnd->substream = NULL; - go->snd_context = gosnd; - v4l2_device_get(&go->v4l2_dev); - ++dev; - - return 0; -} -EXPORT_SYMBOL(go7007_snd_init); - -int go7007_snd_remove(struct go7007 *go) -{ - struct go7007_snd *gosnd = go->snd_context; - - snd_card_disconnect(gosnd->card); - snd_card_free_when_closed(gosnd->card); - v4l2_device_put(&go->v4l2_dev); - return 0; -} -EXPORT_SYMBOL(go7007_snd_remove); - -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/media/lirc/lirc_igorplugusb.c b/drivers/staging/media/lirc/lirc_igorplugusb.c index 44b0d0766084..431d1e86ebf9 100644 --- a/drivers/staging/media/lirc/lirc_igorplugusb.c +++ b/drivers/staging/media/lirc/lirc_igorplugusb.c @@ -209,12 +209,6 @@ static int unregister_from_lirc(struct igorplug *ir) struct lirc_driver *d; int devnum; - if (!ir) { - dev_err(&ir->usbdev->dev, - "%s: called with NULL device struct!\n", __func__); - return -EINVAL; - } - devnum = ir->devnum; d = ir->d; diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index a5b62eec5e21..96c76b33770b 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -189,6 +189,7 @@ MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)"); static void free_imon_context(struct imon_context *context) { struct device *dev = context->driver->dev; + usb_free_urb(context->tx_urb); usb_free_urb(context->rx_urb); lirc_buffer_free(context->driver->rbuf); @@ -481,8 +482,6 @@ static void usb_tx_callback(struct urb *urb) /* notify waiters that write has finished */ atomic_set(&context->tx.busy, 0); complete(&context->tx.finished); - - return; } /** @@ -547,7 +546,6 @@ static void ir_close(void *data) } mutex_unlock(&context->ctx_lock); - return; } /** @@ -572,7 +570,6 @@ static void submit_data(struct imon_context *context) lirc_buffer_write(context->driver->rbuf, buf); wake_up(&context->driver->rbuf->wait_poll); - return; } static inline int tv2int(const struct timeval *a, const struct timeval *b) @@ -656,6 +653,7 @@ static void imon_incoming_packet(struct imon_context *context, mask = 0x80; for (bit = 0; bit < 8; ++bit) { int curr_bit = !(buf[octet] & mask); + if (curr_bit != context->rx.prev_bit) { if (context->rx.count) { submit_data(context); @@ -707,8 +705,6 @@ static void usb_rx_callback(struct urb *urb) } usb_submit_urb(context->rx_urb, GFP_ATOMIC); - - return; } /** @@ -775,6 +771,7 @@ static int imon_probe(struct usb_interface *interface, struct usb_endpoint_descriptor *ep; int ep_dir; int ep_type; + ep = &iface_desc->endpoint[i].desc; ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index 1394f020e46b..672858a089f3 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -169,23 +169,22 @@ static unsigned int init_lirc_timer(void) newtimer = (1000000*count)/timeelapsed; pr_info("%u Hz timer detected\n", newtimer); return newtimer; - } else { - newtimer = (1000000*count)/timeelapsed; - if (abs(newtimer - default_timer) > default_timer/10) { - /* bad timer */ - pr_notice("bad timer: %u Hz\n", newtimer); - pr_notice("using default timer: %u Hz\n", - default_timer); - return default_timer; - } else { - pr_info("%u Hz timer detected\n", newtimer); - return newtimer; /* use detected value */ - } } - } else { - pr_notice("no timer detected\n"); - return 0; + newtimer = (1000000*count)/timeelapsed; + if (abs(newtimer - default_timer) > default_timer/10) { + /* bad timer */ + pr_notice("bad timer: %u Hz\n", newtimer); + pr_notice("using default timer: %u Hz\n", + default_timer); + return default_timer; + } else { + pr_info("%u Hz timer detected\n", newtimer); + return newtimer; /* use detected value */ + } } + + pr_notice("no timer detected\n"); + return 0; } static int lirc_claim(void) @@ -661,7 +660,8 @@ static int __init lirc_parallel_init(void) goto exit_device_put; } ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME, - pf, kf, lirc_lirc_irq_handler, 0, NULL); + pf, kf, lirc_lirc_irq_handler, 0, + NULL); parport_put_port(pport); if (ppdevice == NULL) { pr_notice("parport_register_device() failed\n"); diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c index efe561cd0935..bae0d467093e 100644 --- a/drivers/staging/media/lirc/lirc_serial.c +++ b/drivers/staging/media/lirc/lirc_serial.c @@ -782,7 +782,7 @@ static int lirc_serial_probe(struct platform_device *dev) { int i, nlow, nhigh, result; - result = request_irq(irq, lirc_irq_handler, + result = devm_request_irq(&dev->dev, irq, lirc_irq_handler, (share_irq ? IRQF_SHARED : 0), LIRC_DRIVER_NAME, (void *)&hardware); if (result < 0) { @@ -800,22 +800,22 @@ static int lirc_serial_probe(struct platform_device *dev) * for the NSLU2 it's done in boot code. */ if (((iommap != 0) - && (request_mem_region(iommap, 8 << ioshift, - LIRC_DRIVER_NAME) == NULL)) + && (devm_request_mem_region(&dev->dev, iommap, 8 << ioshift, + LIRC_DRIVER_NAME) == NULL)) || ((iommap == 0) - && (request_region(io, 8, LIRC_DRIVER_NAME) == NULL))) { + && (devm_request_region(&dev->dev, io, 8, + LIRC_DRIVER_NAME) == NULL))) { dev_err(&dev->dev, "port %04x already in use\n", io); dev_warn(&dev->dev, "use 'setserial /dev/ttySX uart none'\n"); dev_warn(&dev->dev, "or compile the serial port driver as module and\n"); dev_warn(&dev->dev, "make sure this module is loaded first\n"); - result = -EBUSY; - goto exit_free_irq; + return -EBUSY; } result = hardware_init_port(); if (result < 0) - goto exit_release_region; + return result; /* Initialize pulse/space widths */ init_timing_params(duty_cycle, freq); @@ -847,28 +847,6 @@ static int lirc_serial_probe(struct platform_device *dev) dprintk("Interrupt %d, port %04x obtained\n", irq, io); return 0; - -exit_release_region: - if (iommap != 0) - release_mem_region(iommap, 8 << ioshift); - else - release_region(io, 8); -exit_free_irq: - free_irq(irq, (void *)&hardware); - - return result; -} - -static int lirc_serial_remove(struct platform_device *dev) -{ - free_irq(irq, (void *)&hardware); - - if (iommap != 0) - release_mem_region(iommap, 8 << ioshift); - else - release_region(io, 8); - - return 0; } static int set_use_inc(void *data) @@ -1081,7 +1059,6 @@ static int lirc_serial_resume(struct platform_device *dev) static struct platform_driver lirc_serial_driver = { .probe = lirc_serial_probe, - .remove = lirc_serial_remove, .suspend = lirc_serial_suspend, .resume = lirc_serial_resume, .driver = { diff --git a/drivers/staging/media/msi3101/Kconfig b/drivers/staging/media/msi3101/Kconfig deleted file mode 100644 index de0b3bba3873..000000000000 --- a/drivers/staging/media/msi3101/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -config USB_MSI3101 - tristate "Mirics MSi3101 SDR Dongle" - depends on USB && VIDEO_DEV && VIDEO_V4L2 && SPI - select VIDEOBUF2_CORE - select VIDEOBUF2_VMALLOC - select MEDIA_TUNER_MSI001 - -config MEDIA_TUNER_MSI001 - tristate "Mirics MSi001" - depends on VIDEO_V4L2 && SPI diff --git a/drivers/staging/media/msi3101/Makefile b/drivers/staging/media/msi3101/Makefile deleted file mode 100644 index daf4f58d9a56..000000000000 --- a/drivers/staging/media/msi3101/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_USB_MSI3101) += sdr-msi3101.o -obj-$(CONFIG_MEDIA_TUNER_MSI001) += msi001.o diff --git a/drivers/staging/media/msi3101/msi001.c b/drivers/staging/media/msi3101/msi001.c deleted file mode 100644 index bd0b93cb6c53..000000000000 --- a/drivers/staging/media/msi3101/msi001.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * Mirics MSi001 silicon tuner driver - * - * Copyright (C) 2013 Antti Palosaari <crope@iki.fi> - * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> - * - * 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. - */ - -#include <linux/module.h> -#include <linux/gcd.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ctrls.h> - -static const struct v4l2_frequency_band bands[] = { - { - .type = V4L2_TUNER_RF, - .index = 0, - .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 49000000, - .rangehigh = 263000000, - }, { - .type = V4L2_TUNER_RF, - .index = 1, - .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 390000000, - .rangehigh = 960000000, - }, -}; - -struct msi001 { - struct spi_device *spi; - struct v4l2_subdev sd; - - /* Controls */ - struct v4l2_ctrl_handler hdl; - struct v4l2_ctrl *bandwidth_auto; - struct v4l2_ctrl *bandwidth; - struct v4l2_ctrl *lna_gain; - struct v4l2_ctrl *mixer_gain; - struct v4l2_ctrl *if_gain; - - unsigned int f_tuner; -}; - -static inline struct msi001 *sd_to_msi001(struct v4l2_subdev *sd) -{ - return container_of(sd, struct msi001, sd); -} - -static int msi001_wreg(struct msi001 *s, u32 data) -{ - /* Register format: 4 bits addr + 20 bits value */ - return spi_write(s->spi, &data, 3); -}; - -static int msi001_set_gain(struct msi001 *s, int lna_gain, int mixer_gain, - int if_gain) -{ - int ret; - u32 reg; - dev_dbg(&s->spi->dev, "%s: lna=%d mixer=%d if=%d\n", __func__, - lna_gain, mixer_gain, if_gain); - - reg = 1 << 0; - reg |= (59 - if_gain) << 4; - reg |= 0 << 10; - reg |= (1 - mixer_gain) << 12; - reg |= (1 - lna_gain) << 13; - reg |= 4 << 14; - reg |= 0 << 17; - ret = msi001_wreg(s, reg); - if (ret) - goto err; - - return 0; -err: - dev_dbg(&s->spi->dev, "%s: failed %d\n", __func__, ret); - return ret; -}; - -static int msi001_set_tuner(struct msi001 *s) -{ - int ret, i; - unsigned int n, m, thresh, frac, vco_step, tmp, f_if1; - u32 reg; - u64 f_vco, tmp64; - u8 mode, filter_mode, lo_div; - static const struct { - u32 rf; - u8 mode; - u8 lo_div; - } band_lut[] = { - { 50000000, 0xe1, 16}, /* AM_MODE2, antenna 2 */ - {108000000, 0x42, 32}, /* VHF_MODE */ - {330000000, 0x44, 16}, /* B3_MODE */ - {960000000, 0x48, 4}, /* B45_MODE */ - { ~0U, 0x50, 2}, /* BL_MODE */ - }; - static const struct { - u32 freq; - u8 filter_mode; - } if_freq_lut[] = { - { 0, 0x03}, /* Zero IF */ - { 450000, 0x02}, /* 450 kHz IF */ - {1620000, 0x01}, /* 1.62 MHz IF */ - {2048000, 0x00}, /* 2.048 MHz IF */ - }; - static const struct { - u32 freq; - u8 val; - } bandwidth_lut[] = { - { 200000, 0x00}, /* 200 kHz */ - { 300000, 0x01}, /* 300 kHz */ - { 600000, 0x02}, /* 600 kHz */ - {1536000, 0x03}, /* 1.536 MHz */ - {5000000, 0x04}, /* 5 MHz */ - {6000000, 0x05}, /* 6 MHz */ - {7000000, 0x06}, /* 7 MHz */ - {8000000, 0x07}, /* 8 MHz */ - }; - - unsigned int f_rf = s->f_tuner; - - /* - * bandwidth (Hz) - * 200000, 300000, 600000, 1536000, 5000000, 6000000, 7000000, 8000000 - */ - unsigned int bandwidth; - - /* - * intermediate frequency (Hz) - * 0, 450000, 1620000, 2048000 - */ - unsigned int f_if = 0; - #define F_REF 24000000 - #define R_REF 4 - #define F_OUT_STEP 1 - - dev_dbg(&s->spi->dev, - "%s: f_rf=%d f_if=%d\n", - __func__, f_rf, f_if); - - for (i = 0; i < ARRAY_SIZE(band_lut); i++) { - if (f_rf <= band_lut[i].rf) { - mode = band_lut[i].mode; - lo_div = band_lut[i].lo_div; - break; - } - } - - if (i == ARRAY_SIZE(band_lut)) { - ret = -EINVAL; - goto err; - } - - /* AM_MODE is upconverted */ - if ((mode >> 0) & 0x1) - f_if1 = 5 * F_REF; - else - f_if1 = 0; - - for (i = 0; i < ARRAY_SIZE(if_freq_lut); i++) { - if (f_if == if_freq_lut[i].freq) { - filter_mode = if_freq_lut[i].filter_mode; - break; - } - } - - if (i == ARRAY_SIZE(if_freq_lut)) { - ret = -EINVAL; - goto err; - } - - /* filters */ - bandwidth = s->bandwidth->val; - bandwidth = clamp(bandwidth, 200000U, 8000000U); - - for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) { - if (bandwidth <= bandwidth_lut[i].freq) { - bandwidth = bandwidth_lut[i].val; - break; - } - } - - if (i == ARRAY_SIZE(bandwidth_lut)) { - ret = -EINVAL; - goto err; - } - - s->bandwidth->val = bandwidth_lut[i].freq; - - dev_dbg(&s->spi->dev, "%s: bandwidth selected=%d\n", - __func__, bandwidth_lut[i].freq); - - f_vco = (u64) (f_rf + f_if + f_if1) * lo_div; - tmp64 = f_vco; - m = do_div(tmp64, F_REF * R_REF); - n = (unsigned int) tmp64; - - vco_step = F_OUT_STEP * lo_div; - thresh = (F_REF * R_REF) / vco_step; - frac = 1ul * thresh * m / (F_REF * R_REF); - - /* Find out greatest common divisor and divide to smaller. */ - tmp = gcd(thresh, frac); - thresh /= tmp; - frac /= tmp; - - /* Force divide to reg max. Resolution will be reduced. */ - tmp = DIV_ROUND_UP(thresh, 4095); - thresh = DIV_ROUND_CLOSEST(thresh, tmp); - frac = DIV_ROUND_CLOSEST(frac, tmp); - - /* calc real RF set */ - tmp = 1ul * F_REF * R_REF * n; - tmp += 1ul * F_REF * R_REF * frac / thresh; - tmp /= lo_div; - - dev_dbg(&s->spi->dev, - "%s: rf=%u:%u n=%d thresh=%d frac=%d\n", - __func__, f_rf, tmp, n, thresh, frac); - - ret = msi001_wreg(s, 0x00000e); - if (ret) - goto err; - - ret = msi001_wreg(s, 0x000003); - if (ret) - goto err; - - reg = 0 << 0; - reg |= mode << 4; - reg |= filter_mode << 12; - reg |= bandwidth << 14; - reg |= 0x02 << 17; - reg |= 0x00 << 20; - ret = msi001_wreg(s, reg); - if (ret) - goto err; - - reg = 5 << 0; - reg |= thresh << 4; - reg |= 1 << 19; - reg |= 1 << 21; - ret = msi001_wreg(s, reg); - if (ret) - goto err; - - reg = 2 << 0; - reg |= frac << 4; - reg |= n << 16; - ret = msi001_wreg(s, reg); - if (ret) - goto err; - - ret = msi001_set_gain(s, s->lna_gain->cur.val, s->mixer_gain->cur.val, - s->if_gain->cur.val); - if (ret) - goto err; - - reg = 6 << 0; - reg |= 63 << 4; - reg |= 4095 << 10; - ret = msi001_wreg(s, reg); - if (ret) - goto err; - - return 0; -err: - dev_dbg(&s->spi->dev, "%s: failed %d\n", __func__, ret); - return ret; -}; - -static int msi001_s_power(struct v4l2_subdev *sd, int on) -{ - struct msi001 *s = sd_to_msi001(sd); - int ret; - dev_dbg(&s->spi->dev, "%s: on=%d\n", __func__, on); - - if (on) - ret = 0; - else - ret = msi001_wreg(s, 0x000000); - - return ret; -} - -static const struct v4l2_subdev_core_ops msi001_core_ops = { - .s_power = msi001_s_power, -}; - -static int msi001_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v) -{ - struct msi001 *s = sd_to_msi001(sd); - dev_dbg(&s->spi->dev, "%s: index=%d\n", __func__, v->index); - - strlcpy(v->name, "Mirics MSi001", sizeof(v->name)); - v->type = V4L2_TUNER_RF; - v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; - v->rangelow = 49000000; - v->rangehigh = 960000000; - - return 0; -} - -static int msi001_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *v) -{ - struct msi001 *s = sd_to_msi001(sd); - dev_dbg(&s->spi->dev, "%s: index=%d\n", __func__, v->index); - return 0; -} - -static int msi001_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) -{ - struct msi001 *s = sd_to_msi001(sd); - dev_dbg(&s->spi->dev, "%s: tuner=%d\n", __func__, f->tuner); - f->frequency = s->f_tuner; - return 0; -} - -static int msi001_s_frequency(struct v4l2_subdev *sd, - const struct v4l2_frequency *f) -{ - struct msi001 *s = sd_to_msi001(sd); - unsigned int band; - dev_dbg(&s->spi->dev, "%s: tuner=%d type=%d frequency=%u\n", - __func__, f->tuner, f->type, f->frequency); - - if (f->frequency < ((bands[0].rangehigh + bands[1].rangelow) / 2)) - band = 0; - else - band = 1; - s->f_tuner = clamp_t(unsigned int, f->frequency, - bands[band].rangelow, bands[band].rangehigh); - - return msi001_set_tuner(s); -} - -static int msi001_enum_freq_bands(struct v4l2_subdev *sd, - struct v4l2_frequency_band *band) -{ - struct msi001 *s = sd_to_msi001(sd); - dev_dbg(&s->spi->dev, "%s: tuner=%d type=%d index=%d\n", - __func__, band->tuner, band->type, band->index); - - if (band->index >= ARRAY_SIZE(bands)) - return -EINVAL; - - band->capability = bands[band->index].capability; - band->rangelow = bands[band->index].rangelow; - band->rangehigh = bands[band->index].rangehigh; - - return 0; -} - -static const struct v4l2_subdev_tuner_ops msi001_tuner_ops = { - .g_tuner = msi001_g_tuner, - .s_tuner = msi001_s_tuner, - .g_frequency = msi001_g_frequency, - .s_frequency = msi001_s_frequency, - .enum_freq_bands = msi001_enum_freq_bands, -}; - -static const struct v4l2_subdev_ops msi001_ops = { - .core = &msi001_core_ops, - .tuner = &msi001_tuner_ops, -}; - -static int msi001_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct msi001 *s = container_of(ctrl->handler, struct msi001, hdl); - - int ret; - dev_dbg(&s->spi->dev, - "%s: id=%d name=%s val=%d min=%d max=%d step=%d\n", - __func__, ctrl->id, ctrl->name, ctrl->val, - ctrl->minimum, ctrl->maximum, ctrl->step); - - switch (ctrl->id) { - case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO: - case V4L2_CID_RF_TUNER_BANDWIDTH: - ret = msi001_set_tuner(s); - break; - case V4L2_CID_RF_TUNER_LNA_GAIN: - ret = msi001_set_gain(s, s->lna_gain->val, - s->mixer_gain->cur.val, s->if_gain->cur.val); - break; - case V4L2_CID_RF_TUNER_MIXER_GAIN: - ret = msi001_set_gain(s, s->lna_gain->cur.val, - s->mixer_gain->val, s->if_gain->cur.val); - break; - case V4L2_CID_RF_TUNER_IF_GAIN: - ret = msi001_set_gain(s, s->lna_gain->cur.val, - s->mixer_gain->cur.val, s->if_gain->val); - break; - default: - dev_dbg(&s->spi->dev, "%s: unkown control %d\n", - __func__, ctrl->id); - ret = -EINVAL; - } - - return ret; -} - -static const struct v4l2_ctrl_ops msi001_ctrl_ops = { - .s_ctrl = msi001_s_ctrl, -}; - -static int msi001_probe(struct spi_device *spi) -{ - struct msi001 *s; - int ret; - dev_dbg(&spi->dev, "%s:\n", __func__); - - s = kzalloc(sizeof(struct msi001), GFP_KERNEL); - if (s == NULL) { - ret = -ENOMEM; - dev_dbg(&spi->dev, "Could not allocate memory for msi001\n"); - goto err_kfree; - } - - s->spi = spi; - s->f_tuner = bands[0].rangelow; - v4l2_spi_subdev_init(&s->sd, spi, &msi001_ops); - - /* Register controls */ - v4l2_ctrl_handler_init(&s->hdl, 5); - s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops, - V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1); - s->bandwidth = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops, - V4L2_CID_RF_TUNER_BANDWIDTH, 200000, 8000000, 1, 200000); - v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false); - s->lna_gain = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops, - V4L2_CID_RF_TUNER_LNA_GAIN, 0, 1, 1, 1); - s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops, - V4L2_CID_RF_TUNER_MIXER_GAIN, 0, 1, 1, 1); - s->if_gain = v4l2_ctrl_new_std(&s->hdl, &msi001_ctrl_ops, - V4L2_CID_RF_TUNER_IF_GAIN, 0, 59, 1, 0); - if (s->hdl.error) { - ret = s->hdl.error; - dev_err(&s->spi->dev, "Could not initialize controls\n"); - /* control init failed, free handler */ - goto err_ctrl_handler_free; - } - - s->sd.ctrl_handler = &s->hdl; - return 0; - -err_ctrl_handler_free: - v4l2_ctrl_handler_free(&s->hdl); -err_kfree: - kfree(s); - return ret; -} - -static int msi001_remove(struct spi_device *spi) -{ - struct v4l2_subdev *sd = spi_get_drvdata(spi); - struct msi001 *s = sd_to_msi001(sd); - dev_dbg(&spi->dev, "%s:\n", __func__); - - /* - * Registered by v4l2_spi_new_subdev() from master driver, but we must - * unregister it from here. Weird. - */ - v4l2_device_unregister_subdev(&s->sd); - v4l2_ctrl_handler_free(&s->hdl); - kfree(s); - return 0; -} - -static const struct spi_device_id msi001_id[] = { - {"msi001", 0}, - {} -}; -MODULE_DEVICE_TABLE(spi, msi001_id); - -static struct spi_driver msi001_driver = { - .driver = { - .name = "msi001", - .owner = THIS_MODULE, - }, - .probe = msi001_probe, - .remove = msi001_remove, - .id_table = msi001_id, -}; -module_spi_driver(msi001_driver); - -MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); -MODULE_DESCRIPTION("Mirics MSi001"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c deleted file mode 100644 index 08d0d096b881..000000000000 --- a/drivers/staging/media/msi3101/sdr-msi3101.c +++ /dev/null @@ -1,1518 +0,0 @@ -/* - * Mirics MSi3101 SDR Dongle driver - * - * Copyright (C) 2013 Antti Palosaari <crope@iki.fi> - * - * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * That driver is somehow based of pwc driver: - * (C) 1999-2004 Nemosoft Unv. - * (C) 2004-2006 Luc Saillard (luc@saillard.org) - * (C) 2011 Hans de Goede <hdegoede@redhat.com> - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <asm/div64.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-event.h> -#include <linux/usb.h> -#include <media/videobuf2-vmalloc.h> -#include <linux/spi/spi.h> - -/* - * iConfiguration 0 - * bInterfaceNumber 0 - * bAlternateSetting 1 - * bNumEndpoints 1 - * bEndpointAddress 0x81 EP 1 IN - * bmAttributes 1 - * Transfer Type Isochronous - * wMaxPacketSize 0x1400 3x 1024 bytes - * bInterval 1 - */ -#define MAX_ISO_BUFS (8) -#define ISO_FRAMES_PER_DESC (8) -#define ISO_MAX_FRAME_SIZE (3 * 1024) -#define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE) -#define MAX_ISOC_ERRORS 20 - -/* TODO: These should be moved to V4L2 API */ -#define V4L2_PIX_FMT_SDR_S8 v4l2_fourcc('D', 'S', '0', '8') /* signed 8-bit */ -#define V4L2_PIX_FMT_SDR_S12 v4l2_fourcc('D', 'S', '1', '2') /* signed 12-bit */ -#define V4L2_PIX_FMT_SDR_S14 v4l2_fourcc('D', 'S', '1', '4') /* signed 14-bit */ -#define V4L2_PIX_FMT_SDR_MSI2500_384 v4l2_fourcc('M', '3', '8', '4') /* Mirics MSi2500 format 384 */ - -static const struct v4l2_frequency_band bands[] = { - { - .tuner = 0, - .type = V4L2_TUNER_ADC, - .index = 0, - .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 1200000, - .rangehigh = 15000000, - }, -}; - -/* stream formats */ -struct msi3101_format { - char *name; - u32 pixelformat; -}; - -/* format descriptions for capture and preview */ -static struct msi3101_format formats[] = { - { - .name = "IQ U8", - .pixelformat = V4L2_SDR_FMT_CU8, - }, { - .name = "IQ U16LE", - .pixelformat = V4L2_SDR_FMT_CU16LE, -#if 0 - }, { - .name = "8-bit signed", - .pixelformat = V4L2_PIX_FMT_SDR_S8, - }, { - .name = "10+2-bit signed", - .pixelformat = V4L2_PIX_FMT_SDR_MSI2500_384, - }, { - .name = "12-bit signed", - .pixelformat = V4L2_PIX_FMT_SDR_S12, - }, { - .name = "14-bit signed", - .pixelformat = V4L2_PIX_FMT_SDR_S14, -#endif - }, -}; - -static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats); - -/* intermediate buffers with raw data from the USB device */ -struct msi3101_frame_buf { - struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */ - struct list_head list; -}; - -struct msi3101_state { - struct video_device vdev; - struct v4l2_device v4l2_dev; - struct v4l2_subdev *v4l2_subdev; - struct spi_master *master; - - /* videobuf2 queue and queued buffers list */ - struct vb2_queue vb_queue; - struct list_head queued_bufs; - spinlock_t queued_bufs_lock; /* Protects queued_bufs */ - - /* Note if taking both locks v4l2_lock must always be locked first! */ - struct mutex v4l2_lock; /* Protects everything else */ - struct mutex vb_queue_lock; /* Protects vb_queue and capt_file */ - - /* Pointer to our usb_device, will be NULL after unplug */ - struct usb_device *udev; /* Both mutexes most be hold when setting! */ - - unsigned int f_adc; - u32 pixelformat; - - unsigned int isoc_errors; /* number of contiguous ISOC errors */ - unsigned int vb_full; /* vb is full and packets dropped */ - - struct urb *urbs[MAX_ISO_BUFS]; - int (*convert_stream)(struct msi3101_state *s, u8 *dst, u8 *src, - unsigned int src_len); - - /* Controls */ - struct v4l2_ctrl_handler hdl; - - u32 next_sample; /* for track lost packets */ - u32 sample; /* for sample rate calc */ - unsigned long jiffies_next; - unsigned int sample_ctrl_bit[4]; -}; - -/* Private functions */ -static struct msi3101_frame_buf *msi3101_get_next_fill_buf( - struct msi3101_state *s) -{ - unsigned long flags = 0; - struct msi3101_frame_buf *buf = NULL; - - spin_lock_irqsave(&s->queued_bufs_lock, flags); - if (list_empty(&s->queued_bufs)) - goto leave; - - buf = list_entry(s->queued_bufs.next, struct msi3101_frame_buf, list); - list_del(&buf->list); -leave: - spin_unlock_irqrestore(&s->queued_bufs_lock, flags); - return buf; -} - -/* - * +=========================================================================== - * | 00-1023 | USB packet type '504' - * +=========================================================================== - * | 00- 03 | sequence number of first sample in that USB packet - * +--------------------------------------------------------------------------- - * | 04- 15 | garbage - * +--------------------------------------------------------------------------- - * | 16-1023 | samples - * +--------------------------------------------------------------------------- - * signed 8-bit sample - * 504 * 2 = 1008 samples - */ -static int msi3101_convert_stream_504(struct msi3101_state *s, u8 *dst, - u8 *src, unsigned int src_len) -{ - int i, i_max, dst_len = 0; - u32 sample_num[3]; - - /* There could be 1-3 1024 bytes URB frames */ - i_max = src_len / 1024; - - for (i = 0; i < i_max; i++) { - sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0; - if (i == 0 && s->next_sample != sample_num[0]) { - dev_dbg_ratelimited(&s->udev->dev, - "%d samples lost, %d %08x:%08x\n", - sample_num[0] - s->next_sample, - src_len, s->next_sample, sample_num[0]); - } - - /* - * Dump all unknown 'garbage' data - maybe we will discover - * someday if there is something rational... - */ - dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]); - - /* 504 x I+Q samples */ - src += 16; - memcpy(dst, src, 1008); - src += 1008; - dst += 1008; - dst_len += 1008; - } - - /* calculate samping rate and output it in 10 seconds intervals */ - if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) { - unsigned long jiffies_now = jiffies; - unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next); - unsigned int samples = sample_num[i_max - 1] - s->sample; - s->jiffies_next = jiffies_now; - s->sample = sample_num[i_max - 1]; - dev_dbg(&s->udev->dev, - "slen=%d samples=%u msecs=%lu sampling rate=%lu\n", - src_len, samples, msecs, - samples * 1000UL / msecs); - } - - /* next sample (sample = sample + i * 504) */ - s->next_sample = sample_num[i_max - 1] + 504; - - return dst_len; -} - -static int msi3101_convert_stream_504_u8(struct msi3101_state *s, u8 *dst, - u8 *src, unsigned int src_len) -{ - int i, j, i_max, dst_len = 0; - u32 sample_num[3]; - s8 *s8src; - u8 *u8dst; - - /* There could be 1-3 1024 bytes URB frames */ - i_max = src_len / 1024; - u8dst = (u8 *) dst; - - for (i = 0; i < i_max; i++) { - sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0; - if (i == 0 && s->next_sample != sample_num[0]) { - dev_dbg_ratelimited(&s->udev->dev, - "%d samples lost, %d %08x:%08x\n", - sample_num[0] - s->next_sample, - src_len, s->next_sample, sample_num[0]); - } - - /* - * Dump all unknown 'garbage' data - maybe we will discover - * someday if there is something rational... - */ - dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]); - - /* 504 x I+Q samples */ - src += 16; - - s8src = (s8 *) src; - for (j = 0; j < 1008; j++) - *u8dst++ = *s8src++ + 128; - - src += 1008; - dst += 1008; - dst_len += 1008; - } - - /* calculate samping rate and output it in 10 seconds intervals */ - if (unlikely(time_is_before_jiffies(s->jiffies_next))) { -#define MSECS 10000UL - unsigned int samples = sample_num[i_max - 1] - s->sample; - s->jiffies_next = jiffies + msecs_to_jiffies(MSECS); - s->sample = sample_num[i_max - 1]; - dev_dbg(&s->udev->dev, - "slen=%d samples=%u msecs=%lu sampling rate=%lu\n", - src_len, samples, MSECS, - samples * 1000UL / MSECS); - } - - /* next sample (sample = sample + i * 504) */ - s->next_sample = sample_num[i_max - 1] + 504; - - return dst_len; -} - -/* - * +=========================================================================== - * | 00-1023 | USB packet type '384' - * +=========================================================================== - * | 00- 03 | sequence number of first sample in that USB packet - * +--------------------------------------------------------------------------- - * | 04- 15 | garbage - * +--------------------------------------------------------------------------- - * | 16- 175 | samples - * +--------------------------------------------------------------------------- - * | 176- 179 | control bits for previous samples - * +--------------------------------------------------------------------------- - * | 180- 339 | samples - * +--------------------------------------------------------------------------- - * | 340- 343 | control bits for previous samples - * +--------------------------------------------------------------------------- - * | 344- 503 | samples - * +--------------------------------------------------------------------------- - * | 504- 507 | control bits for previous samples - * +--------------------------------------------------------------------------- - * | 508- 667 | samples - * +--------------------------------------------------------------------------- - * | 668- 671 | control bits for previous samples - * +--------------------------------------------------------------------------- - * | 672- 831 | samples - * +--------------------------------------------------------------------------- - * | 832- 835 | control bits for previous samples - * +--------------------------------------------------------------------------- - * | 836- 995 | samples - * +--------------------------------------------------------------------------- - * | 996- 999 | control bits for previous samples - * +--------------------------------------------------------------------------- - * | 1000-1023 | garbage - * +--------------------------------------------------------------------------- - * - * Bytes 4 - 7 could have some meaning? - * - * Control bits for previous samples is 32-bit field, containing 16 x 2-bit - * numbers. This results one 2-bit number for 8 samples. It is likely used for - * for bit shifting sample by given bits, increasing actual sampling resolution. - * Number 2 (0b10) was never seen. - * - * 6 * 16 * 2 * 4 = 768 samples. 768 * 4 = 3072 bytes - */ -static int msi3101_convert_stream_384(struct msi3101_state *s, u8 *dst, - u8 *src, unsigned int src_len) -{ - int i, i_max, dst_len = 0; - u32 sample_num[3]; - - /* There could be 1-3 1024 bytes URB frames */ - i_max = src_len / 1024; - for (i = 0; i < i_max; i++) { - sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0; - if (i == 0 && s->next_sample != sample_num[0]) { - dev_dbg_ratelimited(&s->udev->dev, - "%d samples lost, %d %08x:%08x\n", - sample_num[0] - s->next_sample, - src_len, s->next_sample, sample_num[0]); - } - - /* - * Dump all unknown 'garbage' data - maybe we will discover - * someday if there is something rational... - */ - dev_dbg_ratelimited(&s->udev->dev, - "%*ph %*ph\n", 12, &src[4], 24, &src[1000]); - - /* 384 x I+Q samples */ - src += 16; - memcpy(dst, src, 984); - src += 984 + 24; - dst += 984; - dst_len += 984; - } - - /* calculate samping rate and output it in 10 seconds intervals */ - if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) { - unsigned long jiffies_now = jiffies; - unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next); - unsigned int samples = sample_num[i_max - 1] - s->sample; - s->jiffies_next = jiffies_now; - s->sample = sample_num[i_max - 1]; - dev_dbg(&s->udev->dev, - "slen=%d samples=%u msecs=%lu sampling rate=%lu bits=%d.%d.%d.%d\n", - src_len, samples, msecs, - samples * 1000UL / msecs, - s->sample_ctrl_bit[0], s->sample_ctrl_bit[1], - s->sample_ctrl_bit[2], s->sample_ctrl_bit[3]); - } - - /* next sample (sample = sample + i * 384) */ - s->next_sample = sample_num[i_max - 1] + 384; - - return dst_len; -} - -/* - * +=========================================================================== - * | 00-1023 | USB packet type '336' - * +=========================================================================== - * | 00- 03 | sequence number of first sample in that USB packet - * +--------------------------------------------------------------------------- - * | 04- 15 | garbage - * +--------------------------------------------------------------------------- - * | 16-1023 | samples - * +--------------------------------------------------------------------------- - * signed 12-bit sample - */ -static int msi3101_convert_stream_336(struct msi3101_state *s, u8 *dst, - u8 *src, unsigned int src_len) -{ - int i, i_max, dst_len = 0; - u32 sample_num[3]; - - /* There could be 1-3 1024 bytes URB frames */ - i_max = src_len / 1024; - - for (i = 0; i < i_max; i++) { - sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0; - if (i == 0 && s->next_sample != sample_num[0]) { - dev_dbg_ratelimited(&s->udev->dev, - "%d samples lost, %d %08x:%08x\n", - sample_num[0] - s->next_sample, - src_len, s->next_sample, sample_num[0]); - } - - /* - * Dump all unknown 'garbage' data - maybe we will discover - * someday if there is something rational... - */ - dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]); - - /* 336 x I+Q samples */ - src += 16; - memcpy(dst, src, 1008); - src += 1008; - dst += 1008; - dst_len += 1008; - } - - /* calculate samping rate and output it in 10 seconds intervals */ - if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) { - unsigned long jiffies_now = jiffies; - unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next); - unsigned int samples = sample_num[i_max - 1] - s->sample; - s->jiffies_next = jiffies_now; - s->sample = sample_num[i_max - 1]; - dev_dbg(&s->udev->dev, - "slen=%d samples=%u msecs=%lu sampling rate=%lu\n", - src_len, samples, msecs, - samples * 1000UL / msecs); - } - - /* next sample (sample = sample + i * 336) */ - s->next_sample = sample_num[i_max - 1] + 336; - - return dst_len; -} - -/* - * +=========================================================================== - * | 00-1023 | USB packet type '252' - * +=========================================================================== - * | 00- 03 | sequence number of first sample in that USB packet - * +--------------------------------------------------------------------------- - * | 04- 15 | garbage - * +--------------------------------------------------------------------------- - * | 16-1023 | samples - * +--------------------------------------------------------------------------- - * signed 14-bit sample - */ -static int msi3101_convert_stream_252(struct msi3101_state *s, u8 *dst, - u8 *src, unsigned int src_len) -{ - int i, i_max, dst_len = 0; - u32 sample_num[3]; - - /* There could be 1-3 1024 bytes URB frames */ - i_max = src_len / 1024; - - for (i = 0; i < i_max; i++) { - sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0; - if (i == 0 && s->next_sample != sample_num[0]) { - dev_dbg_ratelimited(&s->udev->dev, - "%d samples lost, %d %08x:%08x\n", - sample_num[0] - s->next_sample, - src_len, s->next_sample, sample_num[0]); - } - - /* - * Dump all unknown 'garbage' data - maybe we will discover - * someday if there is something rational... - */ - dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]); - - /* 252 x I+Q samples */ - src += 16; - memcpy(dst, src, 1008); - src += 1008; - dst += 1008; - dst_len += 1008; - } - - /* calculate samping rate and output it in 10 seconds intervals */ - if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) { - unsigned long jiffies_now = jiffies; - unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next); - unsigned int samples = sample_num[i_max - 1] - s->sample; - s->jiffies_next = jiffies_now; - s->sample = sample_num[i_max - 1]; - dev_dbg(&s->udev->dev, - "slen=%d samples=%u msecs=%lu sampling rate=%lu\n", - src_len, samples, msecs, - samples * 1000UL / msecs); - } - - /* next sample (sample = sample + i * 252) */ - s->next_sample = sample_num[i_max - 1] + 252; - - return dst_len; -} - -static int msi3101_convert_stream_252_u16(struct msi3101_state *s, u8 *dst, - u8 *src, unsigned int src_len) -{ - int i, j, i_max, dst_len = 0; - u32 sample_num[3]; - u16 *u16dst = (u16 *) dst; - struct {signed int x:14;} se; - - /* There could be 1-3 1024 bytes URB frames */ - i_max = src_len / 1024; - - for (i = 0; i < i_max; i++) { - sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0; - if (i == 0 && s->next_sample != sample_num[0]) { - dev_dbg_ratelimited(&s->udev->dev, - "%d samples lost, %d %08x:%08x\n", - sample_num[0] - s->next_sample, - src_len, s->next_sample, sample_num[0]); - } - - /* - * Dump all unknown 'garbage' data - maybe we will discover - * someday if there is something rational... - */ - dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]); - - /* 252 x I+Q samples */ - src += 16; - - for (j = 0; j < 1008; j += 4) { - unsigned int usample[2]; - int ssample[2]; - - usample[0] = src[j + 0] >> 0 | src[j + 1] << 8; - usample[1] = src[j + 2] >> 0 | src[j + 3] << 8; - - /* sign extension from 14-bit to signed int */ - ssample[0] = se.x = usample[0]; - ssample[1] = se.x = usample[1]; - - /* from signed to unsigned */ - usample[0] = ssample[0] + 8192; - usample[1] = ssample[1] + 8192; - - /* from 14-bit to 16-bit */ - *u16dst++ = (usample[0] << 2) | (usample[0] >> 12); - *u16dst++ = (usample[1] << 2) | (usample[1] >> 12); - } - - src += 1008; - dst += 1008; - dst_len += 1008; - } - - /* calculate samping rate and output it in 10 seconds intervals */ - if (unlikely(time_is_before_jiffies(s->jiffies_next))) { -#define MSECS 10000UL - unsigned int samples = sample_num[i_max - 1] - s->sample; - s->jiffies_next = jiffies + msecs_to_jiffies(MSECS); - s->sample = sample_num[i_max - 1]; - dev_dbg(&s->udev->dev, - "slen=%d samples=%u msecs=%lu sampling rate=%lu\n", - src_len, samples, MSECS, - samples * 1000UL / MSECS); - } - - /* next sample (sample = sample + i * 252) */ - s->next_sample = sample_num[i_max - 1] + 252; - - return dst_len; -} - -/* - * This gets called for the Isochronous pipe (stream). This is done in interrupt - * time, so it has to be fast, not crash, and not stall. Neat. - */ -static void msi3101_isoc_handler(struct urb *urb) -{ - struct msi3101_state *s = (struct msi3101_state *)urb->context; - int i, flen, fstatus; - unsigned char *iso_buf = NULL; - struct msi3101_frame_buf *fbuf; - - if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN)) { - dev_dbg(&s->udev->dev, "URB (%p) unlinked %ssynchronuously\n", - urb, urb->status == -ENOENT ? "" : "a"); - return; - } - - if (unlikely(urb->status != 0)) { - dev_dbg(&s->udev->dev, - "msi3101_isoc_handler() called with status %d\n", - urb->status); - /* Give up after a number of contiguous errors */ - if (++s->isoc_errors > MAX_ISOC_ERRORS) - dev_dbg(&s->udev->dev, - "Too many ISOC errors, bailing out\n"); - goto handler_end; - } else { - /* Reset ISOC error counter. We did get here, after all. */ - s->isoc_errors = 0; - } - - /* Compact data */ - for (i = 0; i < urb->number_of_packets; i++) { - void *ptr; - - /* Check frame error */ - fstatus = urb->iso_frame_desc[i].status; - if (unlikely(fstatus)) { - dev_dbg_ratelimited(&s->udev->dev, - "frame=%d/%d has error %d skipping\n", - i, urb->number_of_packets, fstatus); - continue; - } - - /* Check if that frame contains data */ - flen = urb->iso_frame_desc[i].actual_length; - if (unlikely(flen == 0)) - continue; - - iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - - /* Get free framebuffer */ - fbuf = msi3101_get_next_fill_buf(s); - if (unlikely(fbuf == NULL)) { - s->vb_full++; - dev_dbg_ratelimited(&s->udev->dev, - "videobuf is full, %d packets dropped\n", - s->vb_full); - continue; - } - - /* fill framebuffer */ - ptr = vb2_plane_vaddr(&fbuf->vb, 0); - flen = s->convert_stream(s, ptr, iso_buf, flen); - vb2_set_plane_payload(&fbuf->vb, 0, flen); - vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE); - } - -handler_end: - i = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(i != 0)) - dev_dbg(&s->udev->dev, - "Error (%d) re-submitting urb in msi3101_isoc_handler\n", - i); -} - -static void msi3101_iso_stop(struct msi3101_state *s) -{ - int i; - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - /* Unlinking ISOC buffers one by one */ - for (i = 0; i < MAX_ISO_BUFS; i++) { - if (s->urbs[i]) { - dev_dbg(&s->udev->dev, "Unlinking URB %p\n", - s->urbs[i]); - usb_kill_urb(s->urbs[i]); - } - } -} - -static void msi3101_iso_free(struct msi3101_state *s) -{ - int i; - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - /* Freeing ISOC buffers one by one */ - for (i = 0; i < MAX_ISO_BUFS; i++) { - if (s->urbs[i]) { - dev_dbg(&s->udev->dev, "Freeing URB\n"); - if (s->urbs[i]->transfer_buffer) { - usb_free_coherent(s->udev, - s->urbs[i]->transfer_buffer_length, - s->urbs[i]->transfer_buffer, - s->urbs[i]->transfer_dma); - } - usb_free_urb(s->urbs[i]); - s->urbs[i] = NULL; - } - } -} - -/* Both v4l2_lock and vb_queue_lock should be locked when calling this */ -static void msi3101_isoc_cleanup(struct msi3101_state *s) -{ - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - msi3101_iso_stop(s); - msi3101_iso_free(s); -} - -/* Both v4l2_lock and vb_queue_lock should be locked when calling this */ -static int msi3101_isoc_init(struct msi3101_state *s) -{ - struct usb_device *udev; - struct urb *urb; - int i, j, ret; - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - s->isoc_errors = 0; - udev = s->udev; - - ret = usb_set_interface(s->udev, 0, 1); - if (ret) - return ret; - - /* Allocate and init Isochronuous urbs */ - for (i = 0; i < MAX_ISO_BUFS; i++) { - urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); - if (urb == NULL) { - dev_err(&s->udev->dev, - "Failed to allocate urb %d\n", i); - msi3101_isoc_cleanup(s); - return -ENOMEM; - } - s->urbs[i] = urb; - dev_dbg(&s->udev->dev, "Allocated URB at 0x%p\n", urb); - - urb->interval = 1; - urb->dev = udev; - urb->pipe = usb_rcvisocpipe(udev, 0x81); - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - urb->transfer_buffer = usb_alloc_coherent(udev, ISO_BUFFER_SIZE, - GFP_KERNEL, &urb->transfer_dma); - if (urb->transfer_buffer == NULL) { - dev_err(&s->udev->dev, - "Failed to allocate urb buffer %d\n", - i); - msi3101_isoc_cleanup(s); - return -ENOMEM; - } - urb->transfer_buffer_length = ISO_BUFFER_SIZE; - urb->complete = msi3101_isoc_handler; - urb->context = s; - urb->start_frame = 0; - urb->number_of_packets = ISO_FRAMES_PER_DESC; - for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { - urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE; - urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE; - } - } - - /* link */ - for (i = 0; i < MAX_ISO_BUFS; i++) { - ret = usb_submit_urb(s->urbs[i], GFP_KERNEL); - if (ret) { - dev_err(&s->udev->dev, - "isoc_init() submit_urb %d failed with error %d\n", - i, ret); - msi3101_isoc_cleanup(s); - return ret; - } - dev_dbg(&s->udev->dev, "URB 0x%p submitted.\n", s->urbs[i]); - } - - /* All is done... */ - return 0; -} - -/* Must be called with vb_queue_lock hold */ -static void msi3101_cleanup_queued_bufs(struct msi3101_state *s) -{ - unsigned long flags = 0; - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - spin_lock_irqsave(&s->queued_bufs_lock, flags); - while (!list_empty(&s->queued_bufs)) { - struct msi3101_frame_buf *buf; - - buf = list_entry(s->queued_bufs.next, struct msi3101_frame_buf, - list); - list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); - } - spin_unlock_irqrestore(&s->queued_bufs_lock, flags); -} - -/* The user yanked out the cable... */ -static void msi3101_disconnect(struct usb_interface *intf) -{ - struct v4l2_device *v = usb_get_intfdata(intf); - struct msi3101_state *s = - container_of(v, struct msi3101_state, v4l2_dev); - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - mutex_lock(&s->vb_queue_lock); - mutex_lock(&s->v4l2_lock); - /* No need to keep the urbs around after disconnection */ - s->udev = NULL; - v4l2_device_disconnect(&s->v4l2_dev); - video_unregister_device(&s->vdev); - spi_unregister_master(s->master); - mutex_unlock(&s->v4l2_lock); - mutex_unlock(&s->vb_queue_lock); - - v4l2_device_put(&s->v4l2_dev); -} - -static int msi3101_querycap(struct file *file, void *fh, - struct v4l2_capability *cap) -{ - struct msi3101_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); - strlcpy(cap->card, s->vdev.name, sizeof(cap->card)); - usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info)); - cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE | V4L2_CAP_TUNER; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -/* Videobuf2 operations */ -static int msi3101_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, unsigned int *nbuffers, - unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) -{ - struct msi3101_state *s = vb2_get_drv_priv(vq); - dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers); - - /* Absolute min and max number of buffers available for mmap() */ - *nbuffers = clamp_t(unsigned int, *nbuffers, 8, 32); - *nplanes = 1; - /* - * 3, wMaxPacketSize 3x 1024 bytes - * 504, max IQ sample pairs per 1024 frame - * 2, two samples, I and Q - * 2, 16-bit is enough for single sample - */ - sizes[0] = PAGE_ALIGN(3 * 504 * 2 * 2); - dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n", - __func__, *nbuffers, sizes[0]); - return 0; -} - -static void msi3101_buf_queue(struct vb2_buffer *vb) -{ - struct msi3101_state *s = vb2_get_drv_priv(vb->vb2_queue); - struct msi3101_frame_buf *buf = - container_of(vb, struct msi3101_frame_buf, vb); - unsigned long flags = 0; - - /* Check the device has not disconnected between prep and queuing */ - if (unlikely(!s->udev)) { - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); - return; - } - - spin_lock_irqsave(&s->queued_bufs_lock, flags); - list_add_tail(&buf->list, &s->queued_bufs); - spin_unlock_irqrestore(&s->queued_bufs_lock, flags); -} - -#define CMD_WREG 0x41 -#define CMD_START_STREAMING 0x43 -#define CMD_STOP_STREAMING 0x45 -#define CMD_READ_UNKNOW 0x48 - -#define msi3101_dbg_usb_control_msg(udev, r, t, v, _i, b, l) { \ - char *direction; \ - if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ - direction = ">>>"; \ - else \ - direction = "<<<"; \ - dev_dbg(&udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \ - "%s %*ph\n", __func__, t, r, v & 0xff, v >> 8, \ - _i & 0xff, _i >> 8, l & 0xff, l >> 8, direction, l, b); \ -} - -static int msi3101_ctrl_msg(struct msi3101_state *s, u8 cmd, u32 data) -{ - int ret; - u8 request = cmd; - u8 requesttype = USB_DIR_OUT | USB_TYPE_VENDOR; - u16 value = (data >> 0) & 0xffff; - u16 index = (data >> 16) & 0xffff; - - msi3101_dbg_usb_control_msg(s->udev, - request, requesttype, value, index, NULL, 0); - - ret = usb_control_msg(s->udev, usb_sndctrlpipe(s->udev, 0), - request, requesttype, value, index, NULL, 0, 2000); - - if (ret) - dev_err(&s->udev->dev, "%s: failed %d, cmd %02x, data %04x\n", - __func__, ret, cmd, data); - - return ret; -}; - -#define F_REF 24000000 -#define DIV_R_IN 2 -static int msi3101_set_usb_adc(struct msi3101_state *s) -{ - int ret, div_n, div_m, div_r_out, f_sr, f_vco, fract; - u32 reg3, reg4, reg7; - struct v4l2_ctrl *bandwidth_auto; - struct v4l2_ctrl *bandwidth; - - f_sr = s->f_adc; - - /* set tuner, subdev, filters according to sampling rate */ - bandwidth_auto = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO); - if (v4l2_ctrl_g_ctrl(bandwidth_auto)) { - bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH); - v4l2_ctrl_s_ctrl(bandwidth, s->f_adc); - } - - /* select stream format */ - switch (s->pixelformat) { - case V4L2_SDR_FMT_CU8: - s->convert_stream = msi3101_convert_stream_504_u8; - reg7 = 0x000c9407; - break; - case V4L2_SDR_FMT_CU16LE: - s->convert_stream = msi3101_convert_stream_252_u16; - reg7 = 0x00009407; - break; - case V4L2_PIX_FMT_SDR_S8: - s->convert_stream = msi3101_convert_stream_504; - reg7 = 0x000c9407; - break; - case V4L2_PIX_FMT_SDR_MSI2500_384: - s->convert_stream = msi3101_convert_stream_384; - reg7 = 0x0000a507; - break; - case V4L2_PIX_FMT_SDR_S12: - s->convert_stream = msi3101_convert_stream_336; - reg7 = 0x00008507; - break; - case V4L2_PIX_FMT_SDR_S14: - s->convert_stream = msi3101_convert_stream_252; - reg7 = 0x00009407; - break; - default: - s->convert_stream = msi3101_convert_stream_504_u8; - reg7 = 0x000c9407; - break; - } - - /* - * Synthesizer config is just a educated guess... - * - * [7:0] 0x03, register address - * [8] 1, power control - * [9] ?, power control - * [12:10] output divider - * [13] 0 ? - * [14] 0 ? - * [15] fractional MSB, bit 20 - * [16:19] N - * [23:20] ? - * [24:31] 0x01 - * - * output divider - * val div - * 0 - (invalid) - * 1 4 - * 2 6 - * 3 8 - * 4 10 - * 5 12 - * 6 14 - * 7 16 - * - * VCO 202000000 - 720000000++ - */ - reg3 = 0x01000303; - reg4 = 0x00000004; - - /* XXX: Filters? AGC? */ - if (f_sr < 6000000) - reg3 |= 0x1 << 20; - else if (f_sr < 7000000) - reg3 |= 0x5 << 20; - else if (f_sr < 8500000) - reg3 |= 0x9 << 20; - else - reg3 |= 0xd << 20; - - for (div_r_out = 4; div_r_out < 16; div_r_out += 2) { - f_vco = f_sr * div_r_out * 12; - dev_dbg(&s->udev->dev, "%s: div_r_out=%d f_vco=%d\n", - __func__, div_r_out, f_vco); - if (f_vco >= 202000000) - break; - } - - div_n = f_vco / (F_REF * DIV_R_IN); - div_m = f_vco % (F_REF * DIV_R_IN); - fract = 0x200000ul * div_m / (F_REF * DIV_R_IN); - - reg3 |= div_n << 16; - reg3 |= (div_r_out / 2 - 1) << 10; - reg3 |= ((fract >> 20) & 0x000001) << 15; /* [20] */ - reg4 |= ((fract >> 0) & 0x0fffff) << 8; /* [19:0] */ - - dev_dbg(&s->udev->dev, - "%s: f_sr=%d f_vco=%d div_n=%d div_m=%d div_r_out=%d reg3=%08x reg4=%08x\n", - __func__, f_sr, f_vco, div_n, div_m, div_r_out, reg3, reg4); - - ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00608008); - if (ret) - goto err; - - ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00000c05); - if (ret) - goto err; - - ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00020000); - if (ret) - goto err; - - ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00480102); - if (ret) - goto err; - - ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00f38008); - if (ret) - goto err; - - ret = msi3101_ctrl_msg(s, CMD_WREG, reg7); - if (ret) - goto err; - - ret = msi3101_ctrl_msg(s, CMD_WREG, reg4); - if (ret) - goto err; - - ret = msi3101_ctrl_msg(s, CMD_WREG, reg3); - if (ret) - goto err; -err: - return ret; -}; - -static int msi3101_start_streaming(struct vb2_queue *vq, unsigned int count) -{ - struct msi3101_state *s = vb2_get_drv_priv(vq); - int ret; - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - if (!s->udev) - return -ENODEV; - - if (mutex_lock_interruptible(&s->v4l2_lock)) - return -ERESTARTSYS; - - /* wake-up tuner */ - v4l2_subdev_call(s->v4l2_subdev, core, s_power, 1); - - ret = msi3101_set_usb_adc(s); - - ret = msi3101_isoc_init(s); - if (ret) - msi3101_cleanup_queued_bufs(s); - - ret = msi3101_ctrl_msg(s, CMD_START_STREAMING, 0); - - mutex_unlock(&s->v4l2_lock); - - return ret; -} - -static void msi3101_stop_streaming(struct vb2_queue *vq) -{ - struct msi3101_state *s = vb2_get_drv_priv(vq); - - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - mutex_lock(&s->v4l2_lock); - - if (s->udev) - msi3101_isoc_cleanup(s); - - msi3101_cleanup_queued_bufs(s); - - /* according to tests, at least 700us delay is required */ - msleep(20); - if (!msi3101_ctrl_msg(s, CMD_STOP_STREAMING, 0)) { - /* sleep USB IF / ADC */ - msi3101_ctrl_msg(s, CMD_WREG, 0x01000003); - } - - /* sleep tuner */ - v4l2_subdev_call(s->v4l2_subdev, core, s_power, 0); - - mutex_unlock(&s->v4l2_lock); -} - -static struct vb2_ops msi3101_vb2_ops = { - .queue_setup = msi3101_queue_setup, - .buf_queue = msi3101_buf_queue, - .start_streaming = msi3101_start_streaming, - .stop_streaming = msi3101_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -static int msi3101_enum_fmt_sdr_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct msi3101_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index); - - if (f->index >= NUM_FORMATS) - return -EINVAL; - - strlcpy(f->description, formats[f->index].name, sizeof(f->description)); - f->pixelformat = formats[f->index].pixelformat; - - return 0; -} - -static int msi3101_g_fmt_sdr_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct msi3101_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, - (char *)&s->pixelformat); - - memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); - f->fmt.sdr.pixelformat = s->pixelformat; - - return 0; -} - -static int msi3101_s_fmt_sdr_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct msi3101_state *s = video_drvdata(file); - struct vb2_queue *q = &s->vb_queue; - int i; - dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, - (char *)&f->fmt.sdr.pixelformat); - - if (vb2_is_busy(q)) - return -EBUSY; - - memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); - for (i = 0; i < NUM_FORMATS; i++) { - if (formats[i].pixelformat == f->fmt.sdr.pixelformat) { - s->pixelformat = f->fmt.sdr.pixelformat; - return 0; - } - } - - f->fmt.sdr.pixelformat = formats[0].pixelformat; - s->pixelformat = formats[0].pixelformat; - - return 0; -} - -static int msi3101_try_fmt_sdr_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct msi3101_state *s = video_drvdata(file); - int i; - dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, - (char *)&f->fmt.sdr.pixelformat); - - memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); - for (i = 0; i < NUM_FORMATS; i++) { - if (formats[i].pixelformat == f->fmt.sdr.pixelformat) - return 0; - } - - f->fmt.sdr.pixelformat = formats[0].pixelformat; - - return 0; -} - -static int msi3101_s_tuner(struct file *file, void *priv, - const struct v4l2_tuner *v) -{ - struct msi3101_state *s = video_drvdata(file); - int ret; - dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index); - - if (v->index == 0) - ret = 0; - else if (v->index == 1) - ret = v4l2_subdev_call(s->v4l2_subdev, tuner, s_tuner, v); - else - ret = -EINVAL; - - return ret; -} - -static int msi3101_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) -{ - struct msi3101_state *s = video_drvdata(file); - int ret; - dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index); - - if (v->index == 0) { - strlcpy(v->name, "Mirics MSi2500", sizeof(v->name)); - v->type = V4L2_TUNER_ADC; - v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; - v->rangelow = 1200000; - v->rangehigh = 15000000; - ret = 0; - } else if (v->index == 1) { - ret = v4l2_subdev_call(s->v4l2_subdev, tuner, g_tuner, v); - } else { - ret = -EINVAL; - } - - return ret; -} - -static int msi3101_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct msi3101_state *s = video_drvdata(file); - int ret = 0; - dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n", - __func__, f->tuner, f->type); - - if (f->tuner == 0) { - f->frequency = s->f_adc; - ret = 0; - } else if (f->tuner == 1) { - f->type = V4L2_TUNER_RF; - ret = v4l2_subdev_call(s->v4l2_subdev, tuner, g_frequency, f); - } else { - ret = -EINVAL; - } - - return ret; -} - -static int msi3101_s_frequency(struct file *file, void *priv, - const struct v4l2_frequency *f) -{ - struct msi3101_state *s = video_drvdata(file); - int ret; - dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n", - __func__, f->tuner, f->type, f->frequency); - - if (f->tuner == 0) { - s->f_adc = clamp_t(unsigned int, f->frequency, - bands[0].rangelow, - bands[0].rangehigh); - dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n", - __func__, s->f_adc); - ret = msi3101_set_usb_adc(s); - } else if (f->tuner == 1) { - ret = v4l2_subdev_call(s->v4l2_subdev, tuner, s_frequency, f); - } else { - ret = -EINVAL; - } - - return ret; -} - -static int msi3101_enum_freq_bands(struct file *file, void *priv, - struct v4l2_frequency_band *band) -{ - struct msi3101_state *s = video_drvdata(file); - int ret; - dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n", - __func__, band->tuner, band->type, band->index); - - if (band->tuner == 0) { - if (band->index >= ARRAY_SIZE(bands)) { - ret = -EINVAL; - } else { - *band = bands[band->index]; - ret = 0; - } - } else if (band->tuner == 1) { - ret = v4l2_subdev_call(s->v4l2_subdev, tuner, - enum_freq_bands, band); - } else { - ret = -EINVAL; - } - - return ret; -} - -static const struct v4l2_ioctl_ops msi3101_ioctl_ops = { - .vidioc_querycap = msi3101_querycap, - - .vidioc_enum_fmt_sdr_cap = msi3101_enum_fmt_sdr_cap, - .vidioc_g_fmt_sdr_cap = msi3101_g_fmt_sdr_cap, - .vidioc_s_fmt_sdr_cap = msi3101_s_fmt_sdr_cap, - .vidioc_try_fmt_sdr_cap = msi3101_try_fmt_sdr_cap, - - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_create_bufs = vb2_ioctl_create_bufs, - .vidioc_prepare_buf = vb2_ioctl_prepare_buf, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - - .vidioc_g_tuner = msi3101_g_tuner, - .vidioc_s_tuner = msi3101_s_tuner, - - .vidioc_g_frequency = msi3101_g_frequency, - .vidioc_s_frequency = msi3101_s_frequency, - .vidioc_enum_freq_bands = msi3101_enum_freq_bands, - - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_log_status = v4l2_ctrl_log_status, -}; - -static const struct v4l2_file_operations msi3101_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = vb2_fop_release, - .read = vb2_fop_read, - .poll = vb2_fop_poll, - .mmap = vb2_fop_mmap, - .unlocked_ioctl = video_ioctl2, -}; - -static struct video_device msi3101_template = { - .name = "Mirics MSi3101 SDR Dongle", - .release = video_device_release_empty, - .fops = &msi3101_fops, - .ioctl_ops = &msi3101_ioctl_ops, -}; - -static void msi3101_video_release(struct v4l2_device *v) -{ - struct msi3101_state *s = - container_of(v, struct msi3101_state, v4l2_dev); - - v4l2_ctrl_handler_free(&s->hdl); - v4l2_device_unregister(&s->v4l2_dev); - kfree(s); -} - -static int msi3101_transfer_one_message(struct spi_master *master, - struct spi_message *m) -{ - struct msi3101_state *s = spi_master_get_devdata(master); - struct spi_transfer *t; - int ret = 0; - u32 data; - - list_for_each_entry(t, &m->transfers, transfer_list) { - dev_dbg(&s->udev->dev, "%s: msg=%*ph\n", - __func__, t->len, t->tx_buf); - data = 0x09; /* reg 9 is SPI adapter */ - data |= ((u8 *)t->tx_buf)[0] << 8; - data |= ((u8 *)t->tx_buf)[1] << 16; - data |= ((u8 *)t->tx_buf)[2] << 24; - ret = msi3101_ctrl_msg(s, CMD_WREG, data); - } - - m->status = ret; - spi_finalize_current_message(master); - return ret; -} - -static int msi3101_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct msi3101_state *s = NULL; - struct v4l2_subdev *sd; - struct spi_master *master; - int ret; - static struct spi_board_info board_info = { - .modalias = "msi001", - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 12000000, - }; - - s = kzalloc(sizeof(struct msi3101_state), GFP_KERNEL); - if (s == NULL) { - pr_err("Could not allocate memory for msi3101_state\n"); - return -ENOMEM; - } - - mutex_init(&s->v4l2_lock); - mutex_init(&s->vb_queue_lock); - spin_lock_init(&s->queued_bufs_lock); - INIT_LIST_HEAD(&s->queued_bufs); - s->udev = udev; - s->f_adc = bands[0].rangelow; - s->pixelformat = V4L2_SDR_FMT_CU8; - - /* Init videobuf2 queue structure */ - s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE; - s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; - s->vb_queue.drv_priv = s; - s->vb_queue.buf_struct_size = sizeof(struct msi3101_frame_buf); - s->vb_queue.ops = &msi3101_vb2_ops; - s->vb_queue.mem_ops = &vb2_vmalloc_memops; - s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - ret = vb2_queue_init(&s->vb_queue); - if (ret) { - dev_err(&s->udev->dev, "Could not initialize vb2 queue\n"); - goto err_free_mem; - } - - /* Init video_device structure */ - s->vdev = msi3101_template; - s->vdev.queue = &s->vb_queue; - s->vdev.queue->lock = &s->vb_queue_lock; - set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev.flags); - video_set_drvdata(&s->vdev, s); - - /* Register the v4l2_device structure */ - s->v4l2_dev.release = msi3101_video_release; - ret = v4l2_device_register(&intf->dev, &s->v4l2_dev); - if (ret) { - dev_err(&s->udev->dev, - "Failed to register v4l2-device (%d)\n", ret); - goto err_free_mem; - } - - /* SPI master adapter */ - master = spi_alloc_master(&s->udev->dev, 0); - if (master == NULL) { - ret = -ENOMEM; - goto err_unregister_v4l2_dev; - } - - s->master = master; - master->bus_num = 0; - master->num_chipselect = 1; - master->transfer_one_message = msi3101_transfer_one_message; - spi_master_set_devdata(master, s); - ret = spi_register_master(master); - if (ret) { - spi_master_put(master); - goto err_unregister_v4l2_dev; - } - - /* load v4l2 subdevice */ - sd = v4l2_spi_new_subdev(&s->v4l2_dev, master, &board_info); - s->v4l2_subdev = sd; - if (sd == NULL) { - dev_err(&s->udev->dev, "cannot get v4l2 subdevice\n"); - ret = -ENODEV; - goto err_unregister_master; - } - - /* Register controls */ - v4l2_ctrl_handler_init(&s->hdl, 0); - if (s->hdl.error) { - ret = s->hdl.error; - dev_err(&s->udev->dev, "Could not initialize controls\n"); - goto err_free_controls; - } - - /* currently all controls are from subdev */ - v4l2_ctrl_add_handler(&s->hdl, sd->ctrl_handler, NULL); - - s->v4l2_dev.ctrl_handler = &s->hdl; - s->vdev.v4l2_dev = &s->v4l2_dev; - s->vdev.lock = &s->v4l2_lock; - - ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1); - if (ret) { - dev_err(&s->udev->dev, - "Failed to register as video device (%d)\n", - ret); - goto err_unregister_v4l2_dev; - } - dev_info(&s->udev->dev, "Registered as %s\n", - video_device_node_name(&s->vdev)); - - return 0; - -err_free_controls: - v4l2_ctrl_handler_free(&s->hdl); -err_unregister_master: - spi_unregister_master(s->master); -err_unregister_v4l2_dev: - v4l2_device_unregister(&s->v4l2_dev); -err_free_mem: - kfree(s); - return ret; -} - -/* USB device ID list */ -static struct usb_device_id msi3101_id_table[] = { - { USB_DEVICE(0x1df7, 0x2500) }, /* Mirics MSi3101 SDR Dongle */ - { USB_DEVICE(0x2040, 0xd300) }, /* Hauppauge WinTV 133559 LF */ - { } -}; -MODULE_DEVICE_TABLE(usb, msi3101_id_table); - -/* USB subsystem interface */ -static struct usb_driver msi3101_driver = { - .name = KBUILD_MODNAME, - .probe = msi3101_probe, - .disconnect = msi3101_disconnect, - .id_table = msi3101_id_table, -}; - -module_usb_driver(msi3101_driver); - -MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); -MODULE_DESCRIPTION("Mirics MSi3101 SDR Dongle"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index 2e422dde074e..d548371db65a 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -1003,33 +1003,18 @@ static void iss_disable_clocks(struct iss_device *iss) clk_disable(iss->iss_fck); } -static void iss_put_clocks(struct iss_device *iss) -{ - if (iss->iss_fck) { - clk_put(iss->iss_fck); - iss->iss_fck = NULL; - } - - if (iss->iss_ctrlclk) { - clk_put(iss->iss_ctrlclk); - iss->iss_ctrlclk = NULL; - } -} - static int iss_get_clocks(struct iss_device *iss) { - iss->iss_fck = clk_get(iss->dev, "iss_fck"); + iss->iss_fck = devm_clk_get(iss->dev, "iss_fck"); if (IS_ERR(iss->iss_fck)) { dev_err(iss->dev, "Unable to get iss_fck clock info\n"); - iss_put_clocks(iss); return PTR_ERR(iss->iss_fck); } - iss->iss_ctrlclk = clk_get(iss->dev, "iss_ctrlclk"); + iss->iss_ctrlclk = devm_clk_get(iss->dev, "iss_ctrlclk"); if (IS_ERR(iss->iss_ctrlclk)) { dev_err(iss->dev, "Unable to get iss_ctrlclk clock info\n"); - iss_put_clocks(iss); - return PTR_ERR(iss->iss_fck); + return PTR_ERR(iss->iss_ctrlclk); } return 0; @@ -1104,29 +1089,11 @@ static int iss_map_mem_resource(struct platform_device *pdev, { struct resource *mem; - /* request the mem region for the camera registers */ - mem = platform_get_resource(pdev, IORESOURCE_MEM, res); - if (!mem) { - dev_err(iss->dev, "no mem resource?\n"); - return -ENODEV; - } - if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) { - dev_err(iss->dev, - "cannot reserve camera register I/O region\n"); - return -ENODEV; - } - iss->res[res] = mem; + iss->regs[res] = devm_ioremap_resource(iss->dev, mem); - /* map the region */ - iss->regs[res] = ioremap_nocache(mem->start, resource_size(mem)); - if (!iss->regs[res]) { - dev_err(iss->dev, "cannot map camera register I/O region\n"); - return -ENODEV; - } - - return 0; + return PTR_ERR_OR_ZERO(iss->regs[res]); } static void iss_unregister_entities(struct iss_device *iss) @@ -1389,7 +1356,7 @@ static int iss_probe(struct platform_device *pdev) if (pdata == NULL) return -EINVAL; - iss = kzalloc(sizeof(*iss), GFP_KERNEL); + iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL); if (!iss) { dev_err(&pdev->dev, "Could not allocate memory\n"); return -ENOMEM; @@ -1456,7 +1423,8 @@ static int iss_probe(struct platform_device *pdev) goto error_iss; } - if (request_irq(iss->irq_num, iss_isr, IRQF_SHARED, "OMAP4 ISS", iss)) { + if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED, + "OMAP4 ISS", iss)) { dev_err(iss->dev, "Unable to request IRQ\n"); ret = -EINVAL; goto error_iss; @@ -1465,7 +1433,7 @@ static int iss_probe(struct platform_device *pdev) /* Entities */ ret = iss_initialize_modules(iss); if (ret < 0) - goto error_irq; + goto error_iss; ret = iss_register_entities(iss); if (ret < 0) @@ -1477,29 +1445,12 @@ static int iss_probe(struct platform_device *pdev) error_modules: iss_cleanup_modules(iss); -error_irq: - free_irq(iss->irq_num, iss); error_iss: omap4iss_put(iss); error: - iss_put_clocks(iss); - - for (i = 0; i < OMAP4_ISS_MEM_LAST; i++) { - if (iss->regs[i]) { - iounmap(iss->regs[i]); - iss->regs[i] = NULL; - } - - if (iss->res[i]) { - release_mem_region(iss->res[i]->start, - resource_size(iss->res[i])); - iss->res[i] = NULL; - } - } platform_set_drvdata(pdev, NULL); mutex_destroy(&iss->iss_mutex); - kfree(iss); return ret; } @@ -1507,29 +1458,10 @@ error: static int iss_remove(struct platform_device *pdev) { struct iss_device *iss = platform_get_drvdata(pdev); - unsigned int i; iss_unregister_entities(iss); iss_cleanup_modules(iss); - free_irq(iss->irq_num, iss); - iss_put_clocks(iss); - - for (i = 0; i < OMAP4_ISS_MEM_LAST; i++) { - if (iss->regs[i]) { - iounmap(iss->regs[i]); - iss->regs[i] = NULL; - } - - if (iss->res[i]) { - release_mem_region(iss->res[i]->start, - resource_size(iss->res[i])); - iss->res[i] = NULL; - } - } - - kfree(iss); - return 0; } diff --git a/drivers/staging/media/omap4iss/iss.h b/drivers/staging/media/omap4iss/iss.h index 05cd9bf3b41f..734cfeeb0314 100644 --- a/drivers/staging/media/omap4iss/iss.h +++ b/drivers/staging/media/omap4iss/iss.h @@ -97,7 +97,7 @@ struct iss_device { u64 raw_dmamask; struct mutex iss_mutex; /* For handling ref_count field */ - bool crashed; + unsigned int crashed; int has_context; int ref_count; diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c index bf8a65726107..9ae4871928d8 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.c +++ b/drivers/staging/media/omap4iss/iss_csi2.c @@ -317,7 +317,7 @@ static void csi2_ctx_enable(struct iss_csi2_device *csi2, u8 ctxnum, u8 enable) static void csi2_ctx_config(struct iss_csi2_device *csi2, struct iss_csi2_ctx_cfg *ctx) { - u32 reg; + u32 reg = 0; /* Set up CSI2_CTx_CTRL1 */ if (ctx->eof_enabled) diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index cbf455d66f73..943b5b09c632 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -25,6 +25,9 @@ #include "iss_video.h" #include "iss.h" +static unsigned debug; +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "activates debug info"); /* ----------------------------------------------------------------------------- * Helper functions @@ -328,15 +331,6 @@ static int iss_video_buf_prepare(struct vb2_buffer *vb) if (vb2_plane_size(vb, 0) < size) return -ENOBUFS; - /* Refuse to prepare the buffer is the video node has registered an - * error. We don't need to take any lock here as the operation is - * inherently racy. The authoritative check will be performed in the - * queue handler, which can't return an error, this check is just a best - * effort to notify userspace as early as possible. - */ - if (unlikely(video->error)) - return -EIO; - addr = vb2_dma_contig_plane_dma_addr(vb, 0); if (!IS_ALIGNED(addr, 32)) { dev_dbg(video->iss->dev, @@ -360,6 +354,11 @@ static void iss_video_buf_queue(struct vb2_buffer *vb) spin_lock_irqsave(&video->qlock, flags); + /* Mark the buffer is faulty and give it back to the queue immediately + * if the video node has registered an error. vb2 will perform the same + * check when preparing the buffer, but that is inherently racy, so we + * need to handle the race condition with an authoritative check here. + */ if (unlikely(video->error)) { vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); spin_unlock_irqrestore(&video->qlock, flags); @@ -510,6 +509,7 @@ void omap4iss_video_cancel_stream(struct iss_video *video) vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); } + vb2_queue_error(video->queue); video->error = true; spin_unlock_irqrestore(&video->qlock, flags); @@ -895,7 +895,6 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) video->queue = &vfh->queue; INIT_LIST_HEAD(&video->dmaqueue); - spin_lock_init(&video->qlock); video->error = false; atomic_set(&pipe->frame_number, -1); @@ -1044,6 +1043,8 @@ static int iss_video_open(struct file *file) if (handle == NULL) return -ENOMEM; + video->video.debug = debug; + v4l2_fh_init(&handle->vfh, &video->video); v4l2_fh_add(&handle->vfh); @@ -1175,6 +1176,7 @@ int omap4iss_video_init(struct iss_video *video, const char *name) if (ret < 0) return ret; + spin_lock_init(&video->qlock); mutex_init(&video->mutex); atomic_set(&video->active, 0); diff --git a/drivers/staging/media/rtl2832u_sdr/Kconfig b/drivers/staging/media/rtl2832u_sdr/Kconfig deleted file mode 100644 index 3ede5fe8f0a5..000000000000 --- a/drivers/staging/media/rtl2832u_sdr/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -config DVB_RTL2832_SDR - tristate "Realtek RTL2832 SDR" - depends on USB && DVB_CORE && I2C && VIDEO_V4L2 && DVB_USB_RTL28XXU - select DVB_RTL2832 - select VIDEOBUF2_VMALLOC - default m if !MEDIA_SUBDRV_AUTOSELECT - diff --git a/drivers/staging/media/rtl2832u_sdr/Makefile b/drivers/staging/media/rtl2832u_sdr/Makefile deleted file mode 100644 index 7e00a0df4631..000000000000 --- a/drivers/staging/media/rtl2832u_sdr/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o - -ccflags-y += -Idrivers/media/dvb-core -ccflags-y += -Idrivers/media/dvb-frontends -ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/usb/dvb-usb-v2 diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c deleted file mode 100644 index 093df6b6ae35..000000000000 --- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c +++ /dev/null @@ -1,1497 +0,0 @@ -/* - * Realtek RTL2832U SDR driver - * - * Copyright (C) 2013 Antti Palosaari <crope@iki.fi> - * - * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * GNU Radio plugin "gr-kernel" for device usage will be on: - * http://git.linuxtv.org/anttip/gr-kernel.git - * - */ - -#include "dvb_frontend.h" -#include "rtl2832_sdr.h" -#include "dvb_usb.h" - -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-event.h> -#include <media/videobuf2-vmalloc.h> - -#include <linux/jiffies.h> -#include <linux/math64.h> - -#define MAX_BULK_BUFS (10) -#define BULK_BUFFER_SIZE (128 * 512) - -static const struct v4l2_frequency_band bands_adc[] = { - { - .tuner = 0, - .type = V4L2_TUNER_ADC, - .index = 0, - .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 300000, - .rangehigh = 300000, - }, - { - .tuner = 0, - .type = V4L2_TUNER_ADC, - .index = 1, - .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 900001, - .rangehigh = 2800000, - }, - { - .tuner = 0, - .type = V4L2_TUNER_ADC, - .index = 2, - .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 3200000, - .rangehigh = 3200000, - }, -}; - -static const struct v4l2_frequency_band bands_fm[] = { - { - .tuner = 1, - .type = V4L2_TUNER_RF, - .index = 0, - .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 50000000, - .rangehigh = 2000000000, - }, -}; - -/* stream formats */ -struct rtl2832_sdr_format { - char *name; - u32 pixelformat; -}; - -static struct rtl2832_sdr_format formats[] = { - { - .name = "IQ U8", - .pixelformat = V4L2_SDR_FMT_CU8, - }, { - .name = "IQ U16LE (emulated)", - .pixelformat = V4L2_SDR_FMT_CU16LE, - }, -}; - -static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats); - -/* intermediate buffers with raw data from the USB device */ -struct rtl2832_sdr_frame_buf { - struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */ - struct list_head list; -}; - -struct rtl2832_sdr_state { -#define POWER_ON (1 << 1) -#define URB_BUF (1 << 2) - unsigned long flags; - - const struct rtl2832_config *cfg; - struct dvb_frontend *fe; - struct dvb_usb_device *d; - struct i2c_adapter *i2c; - u8 bank; - - struct video_device vdev; - struct v4l2_device v4l2_dev; - - /* videobuf2 queue and queued buffers list */ - struct vb2_queue vb_queue; - struct list_head queued_bufs; - spinlock_t queued_bufs_lock; /* Protects queued_bufs */ - unsigned sequence; /* buffer sequence counter */ - - /* Note if taking both locks v4l2_lock must always be locked first! */ - struct mutex v4l2_lock; /* Protects everything else */ - struct mutex vb_queue_lock; /* Protects vb_queue and capt_file */ - - /* Pointer to our usb_device, will be NULL after unplug */ - struct usb_device *udev; /* Both mutexes most be hold when setting! */ - - unsigned int vb_full; /* vb is full and packets dropped */ - - struct urb *urb_list[MAX_BULK_BUFS]; - int buf_num; - unsigned long buf_size; - u8 *buf_list[MAX_BULK_BUFS]; - dma_addr_t dma_addr[MAX_BULK_BUFS]; - int urbs_initialized; - int urbs_submitted; - - unsigned int f_adc, f_tuner; - u32 pixelformat; - - /* Controls */ - struct v4l2_ctrl_handler hdl; - struct v4l2_ctrl *bandwidth_auto; - struct v4l2_ctrl *bandwidth; - - /* for sample rate calc */ - unsigned int sample; - unsigned int sample_measured; - unsigned long jiffies_next; -}; - -/* write multiple hardware registers */ -static int rtl2832_sdr_wr(struct rtl2832_sdr_state *s, u8 reg, const u8 *val, - int len) -{ - int ret; -#define MAX_WR_LEN 24 -#define MAX_WR_XFER_LEN (MAX_WR_LEN + 1) - u8 buf[MAX_WR_XFER_LEN]; - struct i2c_msg msg[1] = { - { - .addr = s->cfg->i2c_addr, - .flags = 0, - .len = 1 + len, - .buf = buf, - } - }; - - if (WARN_ON(len > MAX_WR_LEN)) - return -EINVAL; - - buf[0] = reg; - memcpy(&buf[1], val, len); - - ret = i2c_transfer(s->i2c, msg, 1); - if (ret == 1) { - ret = 0; - } else { - dev_err(&s->i2c->dev, - "%s: I2C wr failed=%d reg=%02x len=%d\n", - KBUILD_MODNAME, ret, reg, len); - ret = -EREMOTEIO; - } - return ret; -} - -/* read multiple hardware registers */ -static int rtl2832_sdr_rd(struct rtl2832_sdr_state *s, u8 reg, u8 *val, int len) -{ - int ret; - struct i2c_msg msg[2] = { - { - .addr = s->cfg->i2c_addr, - .flags = 0, - .len = 1, - .buf = ®, - }, { - .addr = s->cfg->i2c_addr, - .flags = I2C_M_RD, - .len = len, - .buf = val, - } - }; - - ret = i2c_transfer(s->i2c, msg, 2); - if (ret == 2) { - ret = 0; - } else { - dev_err(&s->i2c->dev, - "%s: I2C rd failed=%d reg=%02x len=%d\n", - KBUILD_MODNAME, ret, reg, len); - ret = -EREMOTEIO; - } - return ret; -} - -/* write multiple registers */ -static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_state *s, u16 reg, - const u8 *val, int len) -{ - int ret; - u8 reg2 = (reg >> 0) & 0xff; - u8 bank = (reg >> 8) & 0xff; - - /* switch bank if needed */ - if (bank != s->bank) { - ret = rtl2832_sdr_wr(s, 0x00, &bank, 1); - if (ret) - return ret; - - s->bank = bank; - } - - return rtl2832_sdr_wr(s, reg2, val, len); -} - -/* read multiple registers */ -static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_state *s, u16 reg, u8 *val, - int len) -{ - int ret; - u8 reg2 = (reg >> 0) & 0xff; - u8 bank = (reg >> 8) & 0xff; - - /* switch bank if needed */ - if (bank != s->bank) { - ret = rtl2832_sdr_wr(s, 0x00, &bank, 1); - if (ret) - return ret; - - s->bank = bank; - } - - return rtl2832_sdr_rd(s, reg2, val, len); -} - -/* write single register */ -static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_state *s, u16 reg, u8 val) -{ - return rtl2832_sdr_wr_regs(s, reg, &val, 1); -} - -#if 0 -/* read single register */ -static int rtl2832_sdr_rd_reg(struct rtl2832_sdr_state *s, u16 reg, u8 *val) -{ - return rtl2832_sdr_rd_regs(s, reg, val, 1); -} -#endif - -/* write single register with mask */ -static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_state *s, u16 reg, - u8 val, u8 mask) -{ - int ret; - u8 tmp; - - /* no need for read if whole reg is written */ - if (mask != 0xff) { - ret = rtl2832_sdr_rd_regs(s, reg, &tmp, 1); - if (ret) - return ret; - - val &= mask; - tmp &= ~mask; - val |= tmp; - } - - return rtl2832_sdr_wr_regs(s, reg, &val, 1); -} - -#if 0 -/* read single register with mask */ -static int rtl2832_sdr_rd_reg_mask(struct rtl2832_sdr_state *s, u16 reg, - u8 *val, u8 mask) -{ - int ret, i; - u8 tmp; - - ret = rtl2832_sdr_rd_regs(s, reg, &tmp, 1); - if (ret) - return ret; - - tmp &= mask; - - /* find position of the first bit */ - for (i = 0; i < 8; i++) { - if ((mask >> i) & 0x01) - break; - } - *val = tmp >> i; - - return 0; -} -#endif - -/* Private functions */ -static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf( - struct rtl2832_sdr_state *s) -{ - unsigned long flags = 0; - struct rtl2832_sdr_frame_buf *buf = NULL; - - spin_lock_irqsave(&s->queued_bufs_lock, flags); - if (list_empty(&s->queued_bufs)) - goto leave; - - buf = list_entry(s->queued_bufs.next, - struct rtl2832_sdr_frame_buf, list); - list_del(&buf->list); -leave: - spin_unlock_irqrestore(&s->queued_bufs_lock, flags); - return buf; -} - -static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s, - void *dst, const u8 *src, unsigned int src_len) -{ - unsigned int dst_len; - - if (s->pixelformat == V4L2_SDR_FMT_CU8) { - /* native stream, no need to convert */ - memcpy(dst, src, src_len); - dst_len = src_len; - } else if (s->pixelformat == V4L2_SDR_FMT_CU16LE) { - /* convert u8 to u16 */ - unsigned int i; - u16 *u16dst = dst; - for (i = 0; i < src_len; i++) - *u16dst++ = (src[i] << 8) | (src[i] >> 0); - dst_len = 2 * src_len; - } else { - dst_len = 0; - } - - /* calculate samping rate and output it in 10 seconds intervals */ - if (unlikely(time_is_before_jiffies(s->jiffies_next))) { -#define MSECS 10000UL - unsigned int samples = s->sample - s->sample_measured; - s->jiffies_next = jiffies + msecs_to_jiffies(MSECS); - s->sample_measured = s->sample; - dev_dbg(&s->udev->dev, - "slen=%d samples=%u msecs=%lu sampling rate=%lu\n", - src_len, samples, MSECS, - samples * 1000UL / MSECS); - } - - /* total number of I+Q pairs */ - s->sample += src_len / 2; - - return dst_len; -} - -/* - * This gets called for the bulk stream pipe. This is done in interrupt - * time, so it has to be fast, not crash, and not stall. Neat. - */ -static void rtl2832_sdr_urb_complete(struct urb *urb) -{ - struct rtl2832_sdr_state *s = urb->context; - struct rtl2832_sdr_frame_buf *fbuf; - - dev_dbg_ratelimited(&s->udev->dev, - "%s: status=%d length=%d/%d errors=%d\n", - __func__, urb->status, urb->actual_length, - urb->transfer_buffer_length, urb->error_count); - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - dev_err_ratelimited(&s->udev->dev, "urb failed=%d\n", - urb->status); - break; - } - - if (likely(urb->actual_length > 0)) { - void *ptr; - unsigned int len; - /* get free framebuffer */ - fbuf = rtl2832_sdr_get_next_fill_buf(s); - if (unlikely(fbuf == NULL)) { - s->vb_full++; - dev_notice_ratelimited(&s->udev->dev, - "videobuf is full, %d packets dropped\n", - s->vb_full); - goto skip; - } - - /* fill framebuffer */ - ptr = vb2_plane_vaddr(&fbuf->vb, 0); - len = rtl2832_sdr_convert_stream(s, ptr, urb->transfer_buffer, - urb->actual_length); - vb2_set_plane_payload(&fbuf->vb, 0, len); - v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp); - fbuf->vb.v4l2_buf.sequence = s->sequence++; - vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE); - } -skip: - usb_submit_urb(urb, GFP_ATOMIC); -} - -static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_state *s) -{ - int i; - - for (i = s->urbs_submitted - 1; i >= 0; i--) { - dev_dbg(&s->udev->dev, "%s: kill urb=%d\n", __func__, i); - /* stop the URB */ - usb_kill_urb(s->urb_list[i]); - } - s->urbs_submitted = 0; - - return 0; -} - -static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_state *s) -{ - int i, ret; - - for (i = 0; i < s->urbs_initialized; i++) { - dev_dbg(&s->udev->dev, "%s: submit urb=%d\n", __func__, i); - ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC); - if (ret) { - dev_err(&s->udev->dev, - "Could not submit urb no. %d - get them all back\n", - i); - rtl2832_sdr_kill_urbs(s); - return ret; - } - s->urbs_submitted++; - } - - return 0; -} - -static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_state *s) -{ - if (s->flags & USB_STATE_URB_BUF) { - while (s->buf_num) { - s->buf_num--; - dev_dbg(&s->udev->dev, "%s: free buf=%d\n", - __func__, s->buf_num); - usb_free_coherent(s->udev, s->buf_size, - s->buf_list[s->buf_num], - s->dma_addr[s->buf_num]); - } - } - s->flags &= ~USB_STATE_URB_BUF; - - return 0; -} - -static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_state *s) -{ - s->buf_num = 0; - s->buf_size = BULK_BUFFER_SIZE; - - dev_dbg(&s->udev->dev, - "%s: all in all I will use %u bytes for streaming\n", - __func__, MAX_BULK_BUFS * BULK_BUFFER_SIZE); - - for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) { - s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev, - BULK_BUFFER_SIZE, GFP_ATOMIC, - &s->dma_addr[s->buf_num]); - if (!s->buf_list[s->buf_num]) { - dev_dbg(&s->udev->dev, "%s: alloc buf=%d failed\n", - __func__, s->buf_num); - rtl2832_sdr_free_stream_bufs(s); - return -ENOMEM; - } - - dev_dbg(&s->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n", - __func__, s->buf_num, - s->buf_list[s->buf_num], - (long long)s->dma_addr[s->buf_num]); - s->flags |= USB_STATE_URB_BUF; - } - - return 0; -} - -static int rtl2832_sdr_free_urbs(struct rtl2832_sdr_state *s) -{ - int i; - - rtl2832_sdr_kill_urbs(s); - - for (i = s->urbs_initialized - 1; i >= 0; i--) { - if (s->urb_list[i]) { - dev_dbg(&s->udev->dev, "%s: free urb=%d\n", - __func__, i); - /* free the URBs */ - usb_free_urb(s->urb_list[i]); - } - } - s->urbs_initialized = 0; - - return 0; -} - -static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s) -{ - int i, j; - - /* allocate the URBs */ - for (i = 0; i < MAX_BULK_BUFS; i++) { - dev_dbg(&s->udev->dev, "%s: alloc urb=%d\n", __func__, i); - s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); - if (!s->urb_list[i]) { - dev_dbg(&s->udev->dev, "%s: failed\n", __func__); - for (j = 0; j < i; j++) - usb_free_urb(s->urb_list[j]); - return -ENOMEM; - } - usb_fill_bulk_urb(s->urb_list[i], - s->udev, - usb_rcvbulkpipe(s->udev, 0x81), - s->buf_list[i], - BULK_BUFFER_SIZE, - rtl2832_sdr_urb_complete, s); - - s->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; - s->urb_list[i]->transfer_dma = s->dma_addr[i]; - s->urbs_initialized++; - } - - return 0; -} - -/* Must be called with vb_queue_lock hold */ -static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s) -{ - unsigned long flags = 0; - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - spin_lock_irqsave(&s->queued_bufs_lock, flags); - while (!list_empty(&s->queued_bufs)) { - struct rtl2832_sdr_frame_buf *buf; - buf = list_entry(s->queued_bufs.next, - struct rtl2832_sdr_frame_buf, list); - list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); - } - spin_unlock_irqrestore(&s->queued_bufs_lock, flags); -} - -/* The user yanked out the cable... */ -static void rtl2832_sdr_release_sec(struct dvb_frontend *fe) -{ - struct rtl2832_sdr_state *s = fe->sec_priv; - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - mutex_lock(&s->vb_queue_lock); - mutex_lock(&s->v4l2_lock); - /* No need to keep the urbs around after disconnection */ - s->udev = NULL; - - v4l2_device_disconnect(&s->v4l2_dev); - video_unregister_device(&s->vdev); - mutex_unlock(&s->v4l2_lock); - mutex_unlock(&s->vb_queue_lock); - - v4l2_device_put(&s->v4l2_dev); - - fe->sec_priv = NULL; -} - -static int rtl2832_sdr_querycap(struct file *file, void *fh, - struct v4l2_capability *cap) -{ - struct rtl2832_sdr_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); - strlcpy(cap->card, s->vdev.name, sizeof(cap->card)); - usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info)); - cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE | V4L2_CAP_TUNER; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -/* Videobuf2 operations */ -static int rtl2832_sdr_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, unsigned int *nbuffers, - unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) -{ - struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); - dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers); - - /* Need at least 8 buffers */ - if (vq->num_buffers + *nbuffers < 8) - *nbuffers = 8 - vq->num_buffers; - *nplanes = 1; - /* 2 = max 16-bit sample returned */ - sizes[0] = PAGE_ALIGN(BULK_BUFFER_SIZE * 2); - dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n", - __func__, *nbuffers, sizes[0]); - return 0; -} - -static int rtl2832_sdr_buf_prepare(struct vb2_buffer *vb) -{ - struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue); - - /* Don't allow queing new buffers after device disconnection */ - if (!s->udev) - return -ENODEV; - - return 0; -} - -static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb) -{ - struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue); - struct rtl2832_sdr_frame_buf *buf = - container_of(vb, struct rtl2832_sdr_frame_buf, vb); - unsigned long flags = 0; - - /* Check the device has not disconnected between prep and queuing */ - if (!s->udev) { - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); - return; - } - - spin_lock_irqsave(&s->queued_bufs_lock, flags); - list_add_tail(&buf->list, &s->queued_bufs); - spin_unlock_irqrestore(&s->queued_bufs_lock, flags); -} - -static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s) -{ - struct dvb_frontend *fe = s->fe; - int ret; - unsigned int f_sr, f_if; - u8 buf[4], u8tmp1, u8tmp2; - u64 u64tmp; - u32 u32tmp; - dev_dbg(&s->udev->dev, "%s: f_adc=%u\n", __func__, s->f_adc); - - if (!test_bit(POWER_ON, &s->flags)) - return 0; - - if (s->f_adc == 0) - return 0; - - f_sr = s->f_adc; - - ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x00\x00", 2); - if (ret) - goto err; - - ret = rtl2832_sdr_wr_regs(s, 0x115, "\x00\x00\x00\x00", 4); - if (ret) - goto err; - - /* get IF from tuner */ - if (fe->ops.tuner_ops.get_if_frequency) - ret = fe->ops.tuner_ops.get_if_frequency(fe, &f_if); - else - ret = -EINVAL; - - if (ret) - goto err; - - /* program IF */ - u64tmp = f_if % s->cfg->xtal; - u64tmp *= 0x400000; - u64tmp = div_u64(u64tmp, s->cfg->xtal); - u64tmp = -u64tmp; - u32tmp = u64tmp & 0x3fffff; - - dev_dbg(&s->udev->dev, "%s: f_if=%u if_ctl=%08x\n", - __func__, f_if, u32tmp); - - buf[0] = (u32tmp >> 16) & 0xff; - buf[1] = (u32tmp >> 8) & 0xff; - buf[2] = (u32tmp >> 0) & 0xff; - - ret = rtl2832_sdr_wr_regs(s, 0x119, buf, 3); - if (ret) - goto err; - - /* BB / IF mode */ - /* POR: 0x1b1=0x1f, 0x008=0x0d, 0x006=0x80 */ - if (f_if) { - u8tmp1 = 0x1a; /* disable Zero-IF */ - u8tmp2 = 0x8d; /* enable ADC I */ - } else { - u8tmp1 = 0x1b; /* enable Zero-IF, DC, IQ */ - u8tmp2 = 0xcd; /* enable ADC I, ADC Q */ - } - - ret = rtl2832_sdr_wr_reg(s, 0x1b1, u8tmp1); - if (ret) - goto err; - - ret = rtl2832_sdr_wr_reg(s, 0x008, u8tmp2); - if (ret) - goto err; - - ret = rtl2832_sdr_wr_reg(s, 0x006, 0x80); - if (ret) - goto err; - - /* program sampling rate (resampling down) */ - u32tmp = div_u64(s->cfg->xtal * 0x400000ULL, f_sr * 4U); - u32tmp <<= 2; - buf[0] = (u32tmp >> 24) & 0xff; - buf[1] = (u32tmp >> 16) & 0xff; - buf[2] = (u32tmp >> 8) & 0xff; - buf[3] = (u32tmp >> 0) & 0xff; - ret = rtl2832_sdr_wr_regs(s, 0x19f, buf, 4); - if (ret) - goto err; - - /* low-pass filter */ - ret = rtl2832_sdr_wr_regs(s, 0x11c, - "\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5", - 20); - if (ret) - goto err; - - ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11\x10", 2); - if (ret) - goto err; - - /* mode */ - ret = rtl2832_sdr_wr_regs(s, 0x019, "\x05", 1); - if (ret) - goto err; - - ret = rtl2832_sdr_wr_regs(s, 0x01a, "\x1b\x16\x0d\x06\x01\xff", 6); - if (ret) - goto err; - - /* FSM */ - ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00\xf0\x0f", 3); - if (ret) - goto err; - - /* PID filter */ - ret = rtl2832_sdr_wr_regs(s, 0x061, "\x60", 1); - if (ret) - goto err; - - /* used RF tuner based settings */ - switch (s->cfg->tuner) { - case RTL2832_TUNER_E4000: - ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1); - ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1); - ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x30", 1); - ret = rtl2832_sdr_wr_regs(s, 0x104, "\xd0", 1); - ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x18", 1); - ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1); - ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1); - ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x011, "\xd4", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x14", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xec", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x83", 1); - ret = rtl2832_sdr_wr_regs(s, 0x010, "\x49", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x87", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00d, "\x85", 1); - ret = rtl2832_sdr_wr_regs(s, 0x013, "\x02", 1); - break; - case RTL2832_TUNER_FC0012: - case RTL2832_TUNER_FC0013: - ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1); - ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1); - ret = rtl2832_sdr_wr_regs(s, 0x103, "\x5a", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x2c", 1); - ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x16", 1); - ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1); - ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1); - ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x011, "\xe9\xbf", 2); - ret = rtl2832_sdr_wr_regs(s, 0x1e5, "\xf0", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1d9, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1db, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1dd, "\x11", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1de, "\xef", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1d8, "\x0c", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1e6, "\x02", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1d7, "\x09", 1); - break; - case RTL2832_TUNER_R820T: - ret = rtl2832_sdr_wr_regs(s, 0x112, "\x5a", 1); - ret = rtl2832_sdr_wr_regs(s, 0x102, "\x40", 1); - ret = rtl2832_sdr_wr_regs(s, 0x115, "\x01", 1); - ret = rtl2832_sdr_wr_regs(s, 0x103, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c7, "\x24", 1); - ret = rtl2832_sdr_wr_regs(s, 0x104, "\xcc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x105, "\xbe", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c8, "\x14", 1); - ret = rtl2832_sdr_wr_regs(s, 0x106, "\x35", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1c9, "\x21", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1ca, "\x21", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1cb, "\x00", 1); - ret = rtl2832_sdr_wr_regs(s, 0x107, "\x40", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1cd, "\x10", 1); - ret = rtl2832_sdr_wr_regs(s, 0x1ce, "\x10", 1); - ret = rtl2832_sdr_wr_regs(s, 0x108, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x109, "\x7f", 1); - ret = rtl2832_sdr_wr_regs(s, 0x10a, "\x80", 1); - ret = rtl2832_sdr_wr_regs(s, 0x10b, "\x7f", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x00e, "\xfc", 1); - ret = rtl2832_sdr_wr_regs(s, 0x011, "\xf4", 1); - break; - default: - dev_notice(&s->udev->dev, "Unsupported tuner\n"); - } - - /* software reset */ - ret = rtl2832_sdr_wr_reg_mask(s, 0x101, 0x04, 0x04); - if (ret) - goto err; - - ret = rtl2832_sdr_wr_reg_mask(s, 0x101, 0x00, 0x04); - if (ret) - goto err; -err: - return ret; -}; - -static void rtl2832_sdr_unset_adc(struct rtl2832_sdr_state *s) -{ - int ret; - - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - /* PID filter */ - ret = rtl2832_sdr_wr_regs(s, 0x061, "\xe0", 1); - if (ret) - goto err; - - /* mode */ - ret = rtl2832_sdr_wr_regs(s, 0x019, "\x20", 1); - if (ret) - goto err; - - ret = rtl2832_sdr_wr_regs(s, 0x017, "\x11\x10", 2); - if (ret) - goto err; - - /* FSM */ - ret = rtl2832_sdr_wr_regs(s, 0x192, "\x00\x0f\xff", 3); - if (ret) - goto err; - - ret = rtl2832_sdr_wr_regs(s, 0x13e, "\x40\x00", 2); - if (ret) - goto err; - - ret = rtl2832_sdr_wr_regs(s, 0x115, "\x06\x3f\xce\xcc", 4); - if (ret) - goto err; -err: - return; -}; - -static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s) -{ - struct dvb_frontend *fe = s->fe; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct v4l2_ctrl *bandwidth_auto; - struct v4l2_ctrl *bandwidth; - - /* - * tuner RF (Hz) - */ - if (s->f_tuner == 0) - return 0; - - /* - * bandwidth (Hz) - */ - bandwidth_auto = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO); - bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH); - if (v4l2_ctrl_g_ctrl(bandwidth_auto)) { - c->bandwidth_hz = s->f_adc; - v4l2_ctrl_s_ctrl(bandwidth, s->f_adc); - } else { - c->bandwidth_hz = v4l2_ctrl_g_ctrl(bandwidth); - } - - c->frequency = s->f_tuner; - c->delivery_system = SYS_DVBT; - - dev_dbg(&s->udev->dev, "%s: frequency=%u bandwidth=%d\n", - __func__, c->frequency, c->bandwidth_hz); - - if (!test_bit(POWER_ON, &s->flags)) - return 0; - - if (fe->ops.tuner_ops.set_params) - fe->ops.tuner_ops.set_params(fe); - - return 0; -}; - -static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s) -{ - struct dvb_frontend *fe = s->fe; - - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - if (fe->ops.tuner_ops.init) - fe->ops.tuner_ops.init(fe); - - return 0; -}; - -static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_state *s) -{ - struct dvb_frontend *fe = s->fe; - - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - if (fe->ops.tuner_ops.sleep) - fe->ops.tuner_ops.sleep(fe); - - return; -}; - -static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count) -{ - struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); - int ret; - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - if (!s->udev) - return -ENODEV; - - if (mutex_lock_interruptible(&s->v4l2_lock)) - return -ERESTARTSYS; - - if (s->d->props->power_ctrl) - s->d->props->power_ctrl(s->d, 1); - - set_bit(POWER_ON, &s->flags); - - ret = rtl2832_sdr_set_tuner(s); - if (ret) - goto err; - - ret = rtl2832_sdr_set_tuner_freq(s); - if (ret) - goto err; - - ret = rtl2832_sdr_set_adc(s); - if (ret) - goto err; - - ret = rtl2832_sdr_alloc_stream_bufs(s); - if (ret) - goto err; - - ret = rtl2832_sdr_alloc_urbs(s); - if (ret) - goto err; - - s->sequence = 0; - - ret = rtl2832_sdr_submit_urbs(s); - if (ret) - goto err; - -err: - mutex_unlock(&s->v4l2_lock); - - return ret; -} - -static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq) -{ - struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - mutex_lock(&s->v4l2_lock); - - rtl2832_sdr_kill_urbs(s); - rtl2832_sdr_free_urbs(s); - rtl2832_sdr_free_stream_bufs(s); - rtl2832_sdr_cleanup_queued_bufs(s); - rtl2832_sdr_unset_adc(s); - rtl2832_sdr_unset_tuner(s); - - clear_bit(POWER_ON, &s->flags); - - if (s->d->props->power_ctrl) - s->d->props->power_ctrl(s->d, 0); - - mutex_unlock(&s->v4l2_lock); -} - -static struct vb2_ops rtl2832_sdr_vb2_ops = { - .queue_setup = rtl2832_sdr_queue_setup, - .buf_prepare = rtl2832_sdr_buf_prepare, - .buf_queue = rtl2832_sdr_buf_queue, - .start_streaming = rtl2832_sdr_start_streaming, - .stop_streaming = rtl2832_sdr_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -static int rtl2832_sdr_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *v) -{ - struct rtl2832_sdr_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s: index=%d type=%d\n", - __func__, v->index, v->type); - - if (v->index == 0) { - strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name)); - v->type = V4L2_TUNER_ADC; - v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; - v->rangelow = 300000; - v->rangehigh = 3200000; - } else if (v->index == 1) { - strlcpy(v->name, "RF: <unknown>", sizeof(v->name)); - v->type = V4L2_TUNER_RF; - v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; - v->rangelow = 50000000; - v->rangehigh = 2000000000; - } else { - return -EINVAL; - } - - return 0; -} - -static int rtl2832_sdr_s_tuner(struct file *file, void *priv, - const struct v4l2_tuner *v) -{ - struct rtl2832_sdr_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - if (v->index > 1) - return -EINVAL; - return 0; -} - -static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv, - struct v4l2_frequency_band *band) -{ - struct rtl2832_sdr_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n", - __func__, band->tuner, band->type, band->index); - - if (band->tuner == 0) { - if (band->index >= ARRAY_SIZE(bands_adc)) - return -EINVAL; - - *band = bands_adc[band->index]; - } else if (band->tuner == 1) { - if (band->index >= ARRAY_SIZE(bands_fm)) - return -EINVAL; - - *band = bands_fm[band->index]; - } else { - return -EINVAL; - } - - return 0; -} - -static int rtl2832_sdr_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct rtl2832_sdr_state *s = video_drvdata(file); - int ret = 0; - dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n", - __func__, f->tuner, f->type); - - if (f->tuner == 0) { - f->frequency = s->f_adc; - f->type = V4L2_TUNER_ADC; - } else if (f->tuner == 1) { - f->frequency = s->f_tuner; - f->type = V4L2_TUNER_RF; - } else { - return -EINVAL; - } - - return ret; -} - -static int rtl2832_sdr_s_frequency(struct file *file, void *priv, - const struct v4l2_frequency *f) -{ - struct rtl2832_sdr_state *s = video_drvdata(file); - int ret, band; - - dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n", - __func__, f->tuner, f->type, f->frequency); - - /* ADC band midpoints */ - #define BAND_ADC_0 ((bands_adc[0].rangehigh + bands_adc[1].rangelow) / 2) - #define BAND_ADC_1 ((bands_adc[1].rangehigh + bands_adc[2].rangelow) / 2) - - if (f->tuner == 0 && f->type == V4L2_TUNER_ADC) { - if (f->frequency < BAND_ADC_0) - band = 0; - else if (f->frequency < BAND_ADC_1) - band = 1; - else - band = 2; - - s->f_adc = clamp_t(unsigned int, f->frequency, - bands_adc[band].rangelow, - bands_adc[band].rangehigh); - - dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n", - __func__, s->f_adc); - ret = rtl2832_sdr_set_adc(s); - } else if (f->tuner == 1) { - s->f_tuner = clamp_t(unsigned int, f->frequency, - bands_fm[0].rangelow, - bands_fm[0].rangehigh); - dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n", - __func__, f->frequency); - - ret = rtl2832_sdr_set_tuner_freq(s); - } else { - ret = -EINVAL; - } - - return ret; -} - -static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct rtl2832_sdr_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - if (f->index >= NUM_FORMATS) - return -EINVAL; - - strlcpy(f->description, formats[f->index].name, sizeof(f->description)); - f->pixelformat = formats[f->index].pixelformat; - - return 0; -} - -static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct rtl2832_sdr_state *s = video_drvdata(file); - dev_dbg(&s->udev->dev, "%s:\n", __func__); - - f->fmt.sdr.pixelformat = s->pixelformat; - memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); - - return 0; -} - -static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct rtl2832_sdr_state *s = video_drvdata(file); - struct vb2_queue *q = &s->vb_queue; - int i; - dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, - (char *)&f->fmt.sdr.pixelformat); - - if (vb2_is_busy(q)) - return -EBUSY; - - memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); - for (i = 0; i < NUM_FORMATS; i++) { - if (formats[i].pixelformat == f->fmt.sdr.pixelformat) { - s->pixelformat = f->fmt.sdr.pixelformat; - return 0; - } - } - - f->fmt.sdr.pixelformat = formats[0].pixelformat; - s->pixelformat = formats[0].pixelformat; - - return 0; -} - -static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct rtl2832_sdr_state *s = video_drvdata(file); - int i; - dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, - (char *)&f->fmt.sdr.pixelformat); - - memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); - for (i = 0; i < NUM_FORMATS; i++) { - if (formats[i].pixelformat == f->fmt.sdr.pixelformat) - return 0; - } - - f->fmt.sdr.pixelformat = formats[0].pixelformat; - - return 0; -} - -static const struct v4l2_ioctl_ops rtl2832_sdr_ioctl_ops = { - .vidioc_querycap = rtl2832_sdr_querycap, - - .vidioc_enum_fmt_sdr_cap = rtl2832_sdr_enum_fmt_sdr_cap, - .vidioc_g_fmt_sdr_cap = rtl2832_sdr_g_fmt_sdr_cap, - .vidioc_s_fmt_sdr_cap = rtl2832_sdr_s_fmt_sdr_cap, - .vidioc_try_fmt_sdr_cap = rtl2832_sdr_try_fmt_sdr_cap, - - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_create_bufs = vb2_ioctl_create_bufs, - .vidioc_prepare_buf = vb2_ioctl_prepare_buf, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - - .vidioc_g_tuner = rtl2832_sdr_g_tuner, - .vidioc_s_tuner = rtl2832_sdr_s_tuner, - - .vidioc_enum_freq_bands = rtl2832_sdr_enum_freq_bands, - .vidioc_g_frequency = rtl2832_sdr_g_frequency, - .vidioc_s_frequency = rtl2832_sdr_s_frequency, - - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_log_status = v4l2_ctrl_log_status, -}; - -static const struct v4l2_file_operations rtl2832_sdr_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = vb2_fop_release, - .read = vb2_fop_read, - .poll = vb2_fop_poll, - .mmap = vb2_fop_mmap, - .unlocked_ioctl = video_ioctl2, -}; - -static struct video_device rtl2832_sdr_template = { - .name = "Realtek RTL2832 SDR", - .release = video_device_release_empty, - .fops = &rtl2832_sdr_fops, - .ioctl_ops = &rtl2832_sdr_ioctl_ops, -}; - -static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct rtl2832_sdr_state *s = - container_of(ctrl->handler, struct rtl2832_sdr_state, - hdl); - struct dvb_frontend *fe = s->fe; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int ret; - dev_dbg(&s->udev->dev, - "%s: id=%d name=%s val=%d min=%d max=%d step=%d\n", - __func__, ctrl->id, ctrl->name, ctrl->val, - ctrl->minimum, ctrl->maximum, ctrl->step); - - switch (ctrl->id) { - case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO: - case V4L2_CID_RF_TUNER_BANDWIDTH: - /* TODO: these controls should be moved to tuner drivers */ - if (s->bandwidth_auto->val) { - /* Round towards the closest legal value */ - s32 val = s->f_adc + s->bandwidth->step / 2; - u32 offset; - val = clamp(val, s->bandwidth->minimum, s->bandwidth->maximum); - offset = val - s->bandwidth->minimum; - offset = s->bandwidth->step * (offset / s->bandwidth->step); - s->bandwidth->val = s->bandwidth->minimum + offset; - } - - c->bandwidth_hz = s->bandwidth->val; - - if (!test_bit(POWER_ON, &s->flags)) - return 0; - - if (fe->ops.tuner_ops.set_params) - ret = fe->ops.tuner_ops.set_params(fe); - else - ret = 0; - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static const struct v4l2_ctrl_ops rtl2832_sdr_ctrl_ops = { - .s_ctrl = rtl2832_sdr_s_ctrl, -}; - -static void rtl2832_sdr_video_release(struct v4l2_device *v) -{ - struct rtl2832_sdr_state *s = - container_of(v, struct rtl2832_sdr_state, v4l2_dev); - - v4l2_ctrl_handler_free(&s->hdl); - v4l2_device_unregister(&s->v4l2_dev); - kfree(s); -} - -struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, - struct i2c_adapter *i2c, const struct rtl2832_config *cfg, - struct v4l2_subdev *sd) -{ - int ret; - struct rtl2832_sdr_state *s; - const struct v4l2_ctrl_ops *ops = &rtl2832_sdr_ctrl_ops; - struct dvb_usb_device *d = i2c_get_adapdata(i2c); - - s = kzalloc(sizeof(struct rtl2832_sdr_state), GFP_KERNEL); - if (s == NULL) { - dev_err(&d->udev->dev, - "Could not allocate memory for rtl2832_sdr_state\n"); - return NULL; - } - - /* setup the state */ - s->fe = fe; - s->d = d; - s->udev = d->udev; - s->i2c = i2c; - s->cfg = cfg; - s->f_adc = bands_adc[0].rangelow; - s->f_tuner = bands_fm[0].rangelow; - s->pixelformat = V4L2_SDR_FMT_CU8; - - mutex_init(&s->v4l2_lock); - mutex_init(&s->vb_queue_lock); - spin_lock_init(&s->queued_bufs_lock); - INIT_LIST_HEAD(&s->queued_bufs); - - /* Init videobuf2 queue structure */ - s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE; - s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; - s->vb_queue.drv_priv = s; - s->vb_queue.buf_struct_size = sizeof(struct rtl2832_sdr_frame_buf); - s->vb_queue.ops = &rtl2832_sdr_vb2_ops; - s->vb_queue.mem_ops = &vb2_vmalloc_memops; - s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - ret = vb2_queue_init(&s->vb_queue); - if (ret) { - dev_err(&s->udev->dev, "Could not initialize vb2 queue\n"); - goto err_free_mem; - } - - /* Register controls */ - switch (s->cfg->tuner) { - case RTL2832_TUNER_E4000: - v4l2_ctrl_handler_init(&s->hdl, 9); - if (sd) - v4l2_ctrl_add_handler(&s->hdl, sd->ctrl_handler, NULL); - break; - case RTL2832_TUNER_R820T: - v4l2_ctrl_handler_init(&s->hdl, 2); - s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1); - s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH, 0, 8000000, 100000, 0); - v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false); - break; - case RTL2832_TUNER_FC0012: - case RTL2832_TUNER_FC0013: - v4l2_ctrl_handler_init(&s->hdl, 2); - s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1); - s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH, 6000000, 8000000, 1000000, 6000000); - v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false); - break; - default: - v4l2_ctrl_handler_init(&s->hdl, 0); - dev_notice(&s->udev->dev, "%s: Unsupported tuner\n", - KBUILD_MODNAME); - goto err_free_controls; - } - - if (s->hdl.error) { - ret = s->hdl.error; - dev_err(&s->udev->dev, "Could not initialize controls\n"); - goto err_free_controls; - } - - /* Init video_device structure */ - s->vdev = rtl2832_sdr_template; - s->vdev.queue = &s->vb_queue; - s->vdev.queue->lock = &s->vb_queue_lock; - set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev.flags); - video_set_drvdata(&s->vdev, s); - - /* Register the v4l2_device structure */ - s->v4l2_dev.release = rtl2832_sdr_video_release; - ret = v4l2_device_register(&s->udev->dev, &s->v4l2_dev); - if (ret) { - dev_err(&s->udev->dev, - "Failed to register v4l2-device (%d)\n", ret); - goto err_free_controls; - } - - s->v4l2_dev.ctrl_handler = &s->hdl; - s->vdev.v4l2_dev = &s->v4l2_dev; - s->vdev.lock = &s->v4l2_lock; - s->vdev.vfl_dir = VFL_DIR_RX; - - ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1); - if (ret) { - dev_err(&s->udev->dev, - "Failed to register as video device (%d)\n", - ret); - goto err_unregister_v4l2_dev; - } - dev_info(&s->udev->dev, "Registered as %s\n", - video_device_node_name(&s->vdev)); - - fe->sec_priv = s; - fe->ops.release_sec = rtl2832_sdr_release_sec; - - dev_info(&s->i2c->dev, "%s: Realtek RTL2832 SDR attached\n", - KBUILD_MODNAME); - return fe; - -err_unregister_v4l2_dev: - v4l2_device_unregister(&s->v4l2_dev); -err_free_controls: - v4l2_ctrl_handler_free(&s->hdl); -err_free_mem: - kfree(s); - return NULL; -} -EXPORT_SYMBOL(rtl2832_sdr_attach); - -MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); -MODULE_DESCRIPTION("Realtek RTL2832 SDR driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h b/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h deleted file mode 100644 index b865fadf184f..000000000000 --- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Realtek RTL2832U SDR driver - * - * Copyright (C) 2013 Antti Palosaari <crope@iki.fi> - * - * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * GNU Radio plugin "gr-kernel" for device usage will be on: - * http://git.linuxtv.org/anttip/gr-kernel.git - * - * TODO: - * Help is very highly welcome for these + all the others you could imagine: - * - move controls to V4L2 API - * - use libv4l2 for stream format conversions - * - gr-kernel: switch to v4l2_mmap (current read eats a lot of cpu) - * - SDRSharp support - */ - -#ifndef RTL2832_SDR_H -#define RTL2832_SDR_H - -#include <linux/kconfig.h> -#include <media/v4l2-subdev.h> - -/* for config struct */ -#include "rtl2832.h" - -#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR) -extern struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, - struct i2c_adapter *i2c, const struct rtl2832_config *cfg, - struct v4l2_subdev *sd); -#else -static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, - struct i2c_adapter *i2c, const struct rtl2832_config *cfg, - struct v4l2_subdev *sd) -{ - dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__); - return NULL; -} -#endif - -#endif /* RTL2832_SDR_H */ diff --git a/drivers/staging/media/sn9c102/Kconfig b/drivers/staging/media/sn9c102/Kconfig deleted file mode 100644 index 10f586befce3..000000000000 --- a/drivers/staging/media/sn9c102/Kconfig +++ /dev/null @@ -1,17 +0,0 @@ -config USB_SN9C102 - tristate "USB SN9C1xx PC Camera Controller support (DEPRECATED)" - depends on VIDEO_V4L2 && MEDIA_USB_SUPPORT && USB - ---help--- - This driver is DEPRECATED, please use the gspca sonixb and - sonixj modules instead. - - Say Y here if you want support for cameras based on SONiX SN9C101, - SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers. - - See <file:drivers/staging/media/sn9c102/sn9c102.txt> for more info. - - If you have webcams that are only supported by this driver and not by - the gspca driver, then contact the linux-media mailinglist. - - To compile this driver as a module, choose M here: the - module will be called sn9c102. diff --git a/drivers/staging/media/sn9c102/Makefile b/drivers/staging/media/sn9c102/Makefile deleted file mode 100644 index 7ecd5a90c7c9..000000000000 --- a/drivers/staging/media/sn9c102/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -sn9c102-objs := sn9c102_core.o \ - sn9c102_hv7131d.o \ - sn9c102_hv7131r.o \ - sn9c102_mi0343.o \ - sn9c102_mi0360.o \ - sn9c102_mt9v111.o \ - sn9c102_ov7630.o \ - sn9c102_ov7660.o \ - sn9c102_pas106b.o \ - sn9c102_pas202bcb.o \ - sn9c102_tas5110c1b.o \ - sn9c102_tas5110d.o \ - sn9c102_tas5130d1b.o - -obj-$(CONFIG_USB_SN9C102) += sn9c102.o diff --git a/drivers/staging/media/sn9c102/sn9c102.h b/drivers/staging/media/sn9c102/sn9c102.h deleted file mode 100644 index 37ca7225fcf7..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102.h +++ /dev/null @@ -1,214 +0,0 @@ -/*************************************************************************** - * V4L2 driver for SN9C1xx PC Camera Controllers * - * * - * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#ifndef _SN9C102_H_ -#define _SN9C102_H_ - -#include <linux/usb.h> -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-device.h> -#include <linux/device.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/time.h> -#include <linux/wait.h> -#include <linux/types.h> -#include <linux/param.h> -#include <linux/rwsem.h> -#include <linux/mutex.h> -#include <linux/string.h> -#include <linux/stddef.h> -#include <linux/kref.h> - -#include "sn9c102_config.h" -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -enum sn9c102_frame_state { - F_UNUSED, - F_QUEUED, - F_GRABBING, - F_DONE, - F_ERROR, -}; - -struct sn9c102_frame_t { - void *bufmem; - struct v4l2_buffer buf; - enum sn9c102_frame_state state; - struct list_head frame; - unsigned long vma_use_count; -}; - -enum sn9c102_dev_state { - DEV_INITIALIZED = 0x01, - DEV_DISCONNECTED = 0x02, - DEV_MISCONFIGURED = 0x04, -}; - -enum sn9c102_io_method { - IO_NONE, - IO_READ, - IO_MMAP, -}; - -enum sn9c102_stream_state { - STREAM_OFF, - STREAM_INTERRUPT, - STREAM_ON, -}; - -typedef char sn9c102_sof_header_t[62]; - -struct sn9c102_sof_t { - sn9c102_sof_header_t header; - u16 bytesread; -}; - -struct sn9c102_sysfs_attr { - u16 reg, i2c_reg; - sn9c102_sof_header_t frame_header; -}; - -struct sn9c102_module_param { - u8 force_munmap; - u16 frame_timeout; -}; - -static DEFINE_MUTEX(sn9c102_sysfs_lock); -static DECLARE_RWSEM(sn9c102_dev_lock); - -struct sn9c102_device { - struct video_device *v4ldev; - - struct v4l2_device v4l2_dev; - - enum sn9c102_bridge bridge; - struct sn9c102_sensor sensor; - - struct usb_device *usbdev; - struct urb *urb[SN9C102_URBS]; - void *transfer_buffer[SN9C102_URBS]; - u8 *control_buffer; - - struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES]; - struct list_head inqueue, outqueue; - u32 frame_count, nbuffers, nreadbuffers; - - enum sn9c102_io_method io; - enum sn9c102_stream_state stream; - - struct v4l2_jpegcompression compression; - - struct sn9c102_sysfs_attr sysfs; - struct sn9c102_sof_t sof; - u16 reg[384]; - - struct sn9c102_module_param module_param; - - struct kref kref; - enum sn9c102_dev_state state; - u8 users; - - struct completion probe; - struct mutex open_mutex, fileop_mutex; - spinlock_t queue_lock; - wait_queue_head_t wait_open, wait_frame, wait_stream; -}; - -/*****************************************************************************/ - -struct sn9c102_device* -sn9c102_match_id(struct sn9c102_device *cam, const struct usb_device_id *id) -{ - return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL; -} - - -void -sn9c102_attach_sensor(struct sn9c102_device *cam, - const struct sn9c102_sensor *sensor) -{ - memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); -} - - -enum sn9c102_bridge -sn9c102_get_bridge(struct sn9c102_device *cam) -{ - return cam->bridge; -} - - -struct sn9c102_sensor *sn9c102_get_sensor(struct sn9c102_device *cam) -{ - return &cam->sensor; -} - -/*****************************************************************************/ - -#undef DBG -#undef KDBG -#ifdef SN9C102_DEBUG -# define DBG(level, fmt, args...) \ -do { \ - if (debug >= (level)) { \ - if ((level) == 1) \ - dev_err(&cam->usbdev->dev, fmt "\n", ## args); \ - else if ((level) == 2) \ - dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ - else if ((level) >= 3) \ - dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __func__, __LINE__ , ## args); \ - } \ -} while (0) -# define V4LDBG(level, name, cmd) \ -do { \ - if (debug >= (level)) \ - v4l_printk_ioctl(name, cmd); \ -} while (0) -# define KDBG(level, fmt, args...) \ -do { \ - if (debug >= (level)) { \ - if ((level) == 1 || (level) == 2) \ - pr_info("sn9c102: " fmt "\n", ## args); \ - else if ((level) == 3) \ - pr_debug("sn9c102: [%s:%d] " fmt "\n", \ - __func__, __LINE__ , ## args); \ - } \ -} while (0) -#else -# define DBG(level, fmt, args...) do { ; } while (0) -# define V4LDBG(level, name, cmd) do { ; } while (0) -# define KDBG(level, fmt, args...) do { ; } while (0) -#endif - -#undef PDBG -#define PDBG(fmt, args...) \ -dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \ - __LINE__ , ## args) - -#undef PDBGG -#define PDBGG(fmt, args...) do { ; } while (0) /* placeholder */ - -#endif /* _SN9C102_H_ */ diff --git a/drivers/staging/media/sn9c102/sn9c102.txt b/drivers/staging/media/sn9c102/sn9c102.txt deleted file mode 100644 index b4f67040403a..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102.txt +++ /dev/null @@ -1,592 +0,0 @@ - - SN9C1xx PC Camera Controllers - Driver for Linux - ============================= - - - Documentation - - - -Index -===== -1. Copyright -2. Disclaimer -3. License -4. Overview and features -5. Module dependencies -6. Module loading -7. Module parameters -8. Optional device control through "sysfs" -9. Supported devices -10. Notes for V4L2 application developers -11. Video frame formats -12. Contact information -13. Credits - - -1. Copyright -============ -Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> - - -2. Disclaimer -============= -SONiX is a trademark of SONiX Technology Company Limited, inc. -This software is not sponsored or developed by SONiX. - - -3. License -========== -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., 675 Mass Ave, Cambridge, MA 02139, USA. - - -4. Overview and features -======================== -This driver attempts to support the video interface of the devices assembling -the SONiX SN9C101, SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers -("SN9C1xx" from now on). - -The driver relies on the Video4Linux2 and USB core modules. It has been -designed to run properly on SMP systems as well. - -The latest version of the SN9C1xx driver can be found at the following URL: -http://www.linux-projects.org/ - -Some of the features of the driver are: - -- full compliance with the Video4Linux2 API (see also "Notes for V4L2 - application developers" paragraph); -- available mmap or read/poll methods for video streaming through isochronous - data transfers; -- automatic detection of image sensor; -- support for built-in microphone interface; -- support for any window resolutions and optional panning within the maximum - pixel area of image sensor; -- image downscaling with arbitrary scaling factors from 1, 2 and 4 in both - directions (see "Notes for V4L2 application developers" paragraph); -- two different video formats for uncompressed or compressed data in low or - high compression quality (see also "Notes for V4L2 application developers" - and "Video frame formats" paragraphs); -- full support for the capabilities of many of the possible image sensors that - can be connected to the SN9C1xx bridges, including, for instance, red, green, - blue and global gain adjustments and exposure (see "Supported devices" - paragraph for details); -- use of default color settings for sunlight conditions; -- dynamic I/O interface for both SN9C1xx and image sensor control and - monitoring (see "Optional device control through 'sysfs'" paragraph); -- dynamic driver control thanks to various module parameters (see "Module - parameters" paragraph); -- up to 64 cameras can be handled at the same time; they can be connected and - disconnected from the host many times without turning off the computer, if - the system supports hotplugging; -- no known bugs. - - -5. Module dependencies -====================== -For it to work properly, the driver needs kernel support for Video4Linux and -USB. - -The following options of the kernel configuration file must be enabled and -corresponding modules must be compiled: - - # Multimedia devices - # - CONFIG_VIDEO_DEV=m - -To enable advanced debugging functionality on the device through /sysfs: - - # Multimedia devices - # - CONFIG_VIDEO_ADV_DEBUG=y - - # USB support - # - CONFIG_USB=m - -In addition, depending on the hardware being used, the modules below are -necessary: - - # USB Host Controller Drivers - # - CONFIG_USB_EHCI_HCD=m - CONFIG_USB_UHCI_HCD=m - CONFIG_USB_OHCI_HCD=m - -The SN9C103, SN9c105 and SN9C120 controllers also provide a built-in microphone -interface. It is supported by the USB Audio driver thanks to the ALSA API: - - # Sound - # - CONFIG_SOUND=y - - # Advanced Linux Sound Architecture - # - CONFIG_SND=m - - # USB devices - # - CONFIG_SND_USB_AUDIO=m - -And finally: - - # USB Multimedia devices - # - CONFIG_USB_SN9C102=m - - -6. Module loading -================= -To use the driver, it is necessary to load the "sn9c102" module into memory -after every other module required: "videodev", "v4l2_common", "compat_ioctl32", -"usbcore" and, depending on the USB host controller you have, "ehci-hcd", -"uhci-hcd" or "ohci-hcd". - -Loading can be done as shown below: - - [root@localhost home]# modprobe sn9c102 - -Note that the module is called "sn9c102" for historic reasons, although it -does not just support the SN9C102. - -At this point all the devices supported by the driver and connected to the USB -ports should be recognized. You can invoke "dmesg" to analyze kernel messages -and verify that the loading process has gone well: - - [user@localhost home]$ dmesg - -or, to isolate all the kernel messages generated by the driver: - - [user@localhost home]$ dmesg | grep sn9c102 - - -7. Module parameters -==================== -Module parameters are listed below: -------------------------------------------------------------------------------- -Name: video_nr -Type: short array (min = 0, max = 64) -Syntax: <-1|n[,...]> -Description: Specify V4L2 minor mode number: - -1 = use next available - n = use minor number n - You can specify up to 64 cameras this way. - For example: - video_nr=-1,2,-1 would assign minor number 2 to the second - recognized camera and use auto for the first one and for every - other camera. -Default: -1 -------------------------------------------------------------------------------- -Name: force_munmap -Type: bool array (min = 0, max = 64) -Syntax: <0|1[,...]> -Description: Force the application to unmap previously mapped buffer memory - before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not - all the applications support this feature. This parameter is - specific for each detected camera. - 0 = do not force memory unmapping - 1 = force memory unmapping (save memory) -Default: 0 -------------------------------------------------------------------------------- -Name: frame_timeout -Type: uint array (min = 0, max = 64) -Syntax: <0|n[,...]> -Description: Timeout for a video frame in seconds before returning an I/O - error; 0 for infinity. This parameter is specific for each - detected camera and can be changed at runtime thanks to the - /sys filesystem interface. -Default: 2 -------------------------------------------------------------------------------- -Name: debug -Type: ushort -Syntax: <n> -Description: Debugging information level, from 0 to 3: - 0 = none (use carefully) - 1 = critical errors - 2 = significant information - 3 = more verbose messages - Level 3 is useful for testing only. It also shows some more - information about the hardware being detected. - This parameter can be changed at runtime thanks to the /sys - filesystem interface. -Default: 2 -------------------------------------------------------------------------------- - - -8. Optional device control through "sysfs" [1] -========================================== -If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled, -it is possible to read and write both the SN9C1xx and the image sensor -registers by using the "sysfs" filesystem interface. - -Every time a supported device is recognized, a write-only file named "green" is -created in the /sys/class/video4linux/videoX directory. You can set the green -channel's gain by writing the desired value to it. The value may range from 0 -to 15 for the SN9C101 or SN9C102 bridges, from 0 to 127 for the SN9C103, -SN9C105 and SN9C120 bridges. -Similarly, only for the SN9C103, SN9C105 and SN9C120 controllers, blue and red -gain control files are available in the same directory, for which accepted -values may range from 0 to 127. - -There are other four entries in the directory above for each registered camera: -"reg", "val", "i2c_reg" and "i2c_val". The first two files control the -SN9C1xx bridge, while the other two control the sensor chip. "reg" and -"i2c_reg" hold the values of the current register index where the following -reading/writing operations are addressed at through "val" and "i2c_val". Their -use is not intended for end-users. Note that "i2c_reg" and "i2c_val" will not -be created if the sensor does not actually support the standard I2C protocol or -its registers are not 8-bit long. Also, remember that you must be logged in as -root before writing to them. - -As an example, suppose we were to want to read the value contained in the -register number 1 of the sensor register table - which is usually the product -identifier - of the camera registered as "/dev/video0": - - [root@localhost #] cd /sys/class/video4linux/video0 - [root@localhost #] echo 1 > i2c_reg - [root@localhost #] cat i2c_val - -Note that "cat" will fail if sensor registers cannot be read. - -Now let's set the green gain's register of the SN9C101 or SN9C102 chips to 2: - - [root@localhost #] echo 0x11 > reg - [root@localhost #] echo 2 > val - -Note that the SN9C1xx always returns 0 when some of its registers are read. -To avoid race conditions, all the I/O accesses to the above files are -serialized. -The sysfs interface also provides the "frame_header" entry, which exports the -frame header of the most recent requested and captured video frame. The header -is always 18-bytes long and is appended to every video frame by the SN9C1xx -controllers. As an example, this additional information can be used by the user -application for implementing auto-exposure features via software. - -The following table describes the frame header exported by the SN9C101 and -SN9C102: - -Byte # Value or bits Description ------- ------------- ----------- -0x00 0xFF Frame synchronisation pattern -0x01 0xFF Frame synchronisation pattern -0x02 0x00 Frame synchronisation pattern -0x03 0xC4 Frame synchronisation pattern -0x04 0xC4 Frame synchronisation pattern -0x05 0x96 Frame synchronisation pattern -0x06 [3:0] Read channel gain control = (1+R_GAIN/8) - [7:4] Blue channel gain control = (1+B_GAIN/8) -0x07 [ 0 ] Compression mode. 0=No compression, 1=Compression enabled - [2:1] Maximum scale factor for compression - [ 3 ] 1 = USB fifo(2K bytes) is full - [ 4 ] 1 = Digital gain is finish - [ 5 ] 1 = Exposure is finish - [7:6] Frame index -0x08 [7:0] Y sum inside Auto-Exposure area (low-byte) -0x09 [7:0] Y sum inside Auto-Exposure area (high-byte) - where Y sum = (R/4 + 5G/16 + B/8) / 32 -0x0A [7:0] Y sum outside Auto-Exposure area (low-byte) -0x0B [7:0] Y sum outside Auto-Exposure area (high-byte) - where Y sum = (R/4 + 5G/16 + B/8) / 128 -0x0C 0xXX Not used -0x0D 0xXX Not used -0x0E 0xXX Not used -0x0F 0xXX Not used -0x10 0xXX Not used -0x11 0xXX Not used - -The following table describes the frame header exported by the SN9C103: - -Byte # Value or bits Description ------- ------------- ----------- -0x00 0xFF Frame synchronisation pattern -0x01 0xFF Frame synchronisation pattern -0x02 0x00 Frame synchronisation pattern -0x03 0xC4 Frame synchronisation pattern -0x04 0xC4 Frame synchronisation pattern -0x05 0x96 Frame synchronisation pattern -0x06 [6:0] Read channel gain control = (1/2+R_GAIN/64) -0x07 [6:0] Blue channel gain control = (1/2+B_GAIN/64) - [7:4] -0x08 [ 0 ] Compression mode. 0=No compression, 1=Compression enabled - [2:1] Maximum scale factor for compression - [ 3 ] 1 = USB fifo(2K bytes) is full - [ 4 ] 1 = Digital gain is finish - [ 5 ] 1 = Exposure is finish - [7:6] Frame index -0x09 [7:0] Y sum inside Auto-Exposure area (low-byte) -0x0A [7:0] Y sum inside Auto-Exposure area (high-byte) - where Y sum = (R/4 + 5G/16 + B/8) / 32 -0x0B [7:0] Y sum outside Auto-Exposure area (low-byte) -0x0C [7:0] Y sum outside Auto-Exposure area (high-byte) - where Y sum = (R/4 + 5G/16 + B/8) / 128 -0x0D [1:0] Audio frame number - [ 2 ] 1 = Audio is recording -0x0E [7:0] Audio summation (low-byte) -0x0F [7:0] Audio summation (high-byte) -0x10 [7:0] Audio sample count -0x11 [7:0] Audio peak data in audio frame - -The AE area (sx, sy, ex, ey) in the active window can be set by programming the -registers 0x1c, 0x1d, 0x1e and 0x1f of the SN9C1xx controllers, where one unit -corresponds to 32 pixels. - -[1] The frame headers exported by the SN9C105 and SN9C120 are not described. - - -9. Supported devices -==================== -None of the names of the companies as well as their products will be mentioned -here. They have never collaborated with the author, so no advertising. - -From the point of view of a driver, what unambiguously identify a device are -its vendor and product USB identifiers. Below is a list of known identifiers of -devices assembling the SN9C1xx PC camera controllers: - -Vendor ID Product ID ---------- ---------- -0x0458 0x7025 -0x045e 0x00f5 -0x045e 0x00f7 -0x0471 0x0327 -0x0471 0x0328 -0x0c45 0x6001 -0x0c45 0x6005 -0x0c45 0x6007 -0x0c45 0x6009 -0x0c45 0x600d -0x0c45 0x6011 -0x0c45 0x6019 -0x0c45 0x6024 -0x0c45 0x6025 -0x0c45 0x6028 -0x0c45 0x6029 -0x0c45 0x602a -0x0c45 0x602b -0x0c45 0x602c -0x0c45 0x602d -0x0c45 0x602e -0x0c45 0x6030 -0x0c45 0x603f -0x0c45 0x6080 -0x0c45 0x6082 -0x0c45 0x6083 -0x0c45 0x6088 -0x0c45 0x608a -0x0c45 0x608b -0x0c45 0x608c -0x0c45 0x608e -0x0c45 0x608f -0x0c45 0x60a0 -0x0c45 0x60a2 -0x0c45 0x60a3 -0x0c45 0x60a8 -0x0c45 0x60aa -0x0c45 0x60ab -0x0c45 0x60ac -0x0c45 0x60ae -0x0c45 0x60af -0x0c45 0x60b0 -0x0c45 0x60b2 -0x0c45 0x60b3 -0x0c45 0x60b8 -0x0c45 0x60ba -0x0c45 0x60bb -0x0c45 0x60bc -0x0c45 0x60be -0x0c45 0x60c0 -0x0c45 0x60c2 -0x0c45 0x60c8 -0x0c45 0x60cc -0x0c45 0x60ea -0x0c45 0x60ec -0x0c45 0x60ef -0x0c45 0x60fa -0x0c45 0x60fb -0x0c45 0x60fc -0x0c45 0x60fe -0x0c45 0x6102 -0x0c45 0x6108 -0x0c45 0x610f -0x0c45 0x6130 -0x0c45 0x6138 -0x0c45 0x613a -0x0c45 0x613b -0x0c45 0x613c -0x0c45 0x613e - -The list above does not imply that all those devices work with this driver: up -until now only the ones that assemble the following pairs of SN9C1xx bridges -and image sensors are supported; kernel messages will always tell you whether -this is the case (see "Module loading" paragraph): - -Image sensor / SN9C1xx bridge | SN9C10[12] SN9C103 SN9C105 SN9C120 -------------------------------------------------------------------------------- -HV7131D Hynix Semiconductor | Yes No No No -HV7131R Hynix Semiconductor | No Yes Yes Yes -MI-0343 Micron Technology | Yes No No No -MI-0360 Micron Technology | No Yes Yes Yes -OV7630 OmniVision Technologies | Yes Yes Yes Yes -OV7660 OmniVision Technologies | No No Yes Yes -PAS106B PixArt Imaging | Yes No No No -PAS202B PixArt Imaging | Yes Yes No No -TAS5110C1B Taiwan Advanced Sensor | Yes No No No -TAS5110D Taiwan Advanced Sensor | Yes No No No -TAS5130D1B Taiwan Advanced Sensor | Yes No No No - -"Yes" means that the pair is supported by the driver, while "No" means that the -pair does not exist or is not supported by the driver. - -Only some of the available control settings of each image sensor are supported -through the V4L2 interface. - -Donations of new models for further testing and support would be much -appreciated. Non-available hardware will not be supported by the author of this -driver. - - -10. Notes for V4L2 application developers -========================================= -This driver follows the V4L2 API specifications. In particular, it enforces two -rules: - -- exactly one I/O method, either "mmap" or "read", is associated with each -file descriptor. Once it is selected, the application must close and reopen the -device to switch to the other I/O method; - -- although it is not mandatory, previously mapped buffer memory should always -be unmapped before calling any "VIDIOC_S_CROP" or "VIDIOC_S_FMT" ioctl's. -The same number of buffers as before will be allocated again to match the size -of the new video frames, so you have to map the buffers again before any I/O -attempts on them. - -Consistently with the hardware limits, this driver also supports image -downscaling with arbitrary scaling factors from 1, 2 and 4 in both directions. -However, the V4L2 API specifications don't correctly define how the scaling -factor can be chosen arbitrarily by the "negotiation" of the "source" and -"target" rectangles. To work around this flaw, we have added the convention -that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the -scaling factor is restored to 1. - -This driver supports two different video formats: the first one is the "8-bit -Sequential Bayer" format and can be used to obtain uncompressed video data -from the device through the current I/O method, while the second one provides -either "raw" compressed video data (without frame headers not related to the -compressed data) or standard JPEG (with frame headers). The compression quality -may vary from 0 to 1 and can be selected or queried thanks to the -VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. For maximum flexibility, -both the default active video format and the default compression quality -depend on how the image sensor being used is initialized. - - -11. Video frame formats [1] -======================= -The SN9C1xx PC Camera Controllers can send images in two possible video -formats over the USB: either native "Sequential RGB Bayer" or compressed. -The compression is used to achieve high frame rates. With regard to the -SN9C101, SN9C102 and SN9C103, the compression is based on the Huffman encoding -algorithm described below, while with regard to the SN9C105 and SN9C120 the -compression is based on the JPEG standard. -The current video format may be selected or queried from the user application -by calling the VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2 -API specifications. - -The name "Sequential Bayer" indicates the organization of the red, green and -blue pixels in one video frame. Each pixel is associated with a 8-bit long -value and is disposed in memory according to the pattern shown below: - -B[0] G[1] B[2] G[3] ... B[m-2] G[m-1] -G[m] R[m+1] G[m+2] R[m+2] ... G[2m-2] R[2m-1] -... -... B[(n-1)(m-2)] G[(n-1)(m-1)] -... G[n(m-2)] R[n(m-1)] - -The above matrix also represents the sequential or progressive read-out mode of -the (n, m) Bayer color filter array used in many CCD or CMOS image sensors. - -The Huffman compressed video frame consists of a bitstream that encodes for -every R, G, or B pixel the difference between the value of the pixel itself and -some reference pixel value. Pixels are organised in the Bayer pattern and the -Bayer sub-pixels are tracked individually and alternatingly. For example, in -the first line values for the B and G1 pixels are alternatingly encoded, while -in the second line values for the G2 and R pixels are alternatingly encoded. - -The pixel reference value is calculated as follows: -- the 4 top left pixels are encoded in raw uncompressed 8-bit format; -- the value in the top two rows is the value of the pixel left of the current - pixel; -- the value in the left column is the value of the pixel above the current - pixel; -- for all other pixels, the reference value is the average of the value of the - pixel on the left and the value of the pixel above the current pixel; -- there is one code in the bitstream that specifies the value of a pixel - directly (in 4-bit resolution); -- pixel values need to be clamped inside the range [0..255] for proper - decoding. - -The algorithm purely describes the conversion from compressed Bayer code used -in the SN9C101, SN9C102 and SN9C103 chips to uncompressed Bayer. Additional -steps are required to convert this to a color image (i.e. a color interpolation -algorithm). - -The following Huffman codes have been found: -0: +0 (relative to reference pixel value) -100: +4 -101: -4? -1110xxxx: set absolute value to xxxx.0000 -1101: +11 -1111: -11 -11001: +20 -110000: -20 -110001: ??? - these codes are apparently not used - -[1] The Huffman compression algorithm has been reverse-engineered and - documented by Bertrik Sikken. - - -12. Contact information -======================= -The author may be contacted by e-mail at <luca.risolia@studio.unibo.it>. - -GPG/PGP encrypted e-mail's are accepted. The GPG key ID of the author is -'FCE635A4'; the public 1024-bit key should be available at any keyserver; -the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'. - - -13. Credits -=========== -Many thanks to following persons for their contribute (listed in alphabetical -order): - -- David Anderson for the donation of a webcam; -- Luca Capello for the donation of a webcam; -- Philippe Coval for having helped testing the PAS202BCA image sensor; -- Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the - donation of a webcam; -- Dennis Heitmann for the donation of a webcam; -- Jon Hollstrom for the donation of a webcam; -- Nick McGill for the donation of a webcam; -- Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB - image sensor; -- Stefano Mozzi, who donated 45 EU; -- Andrew Pearce for the donation of a webcam; -- John Pullan for the donation of a webcam; -- Bertrik Sikken, who reverse-engineered and documented the Huffman compression - algorithm used in the SN9C101, SN9C102 and SN9C103 controllers and - implemented the first decoder; -- Ronny Standke for the donation of a webcam; -- Mizuno Takafumi for the donation of a webcam; -- an "anonymous" donator (who didn't want his name to be revealed) for the - donation of a webcam. -- an anonymous donator for the donation of four webcams and two boards with ten - image sensors. diff --git a/drivers/staging/media/sn9c102/sn9c102_config.h b/drivers/staging/media/sn9c102/sn9c102_config.h deleted file mode 100644 index 0f4e0378b071..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_config.h +++ /dev/null @@ -1,86 +0,0 @@ -/*************************************************************************** - * Global parameters for the V4L2 driver for SN9C1xx PC Camera Controllers * - * * - * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#ifndef _SN9C102_CONFIG_H_ -#define _SN9C102_CONFIG_H_ - -#include <linux/types.h> -#include <linux/jiffies.h> - -#define SN9C102_DEBUG -#define SN9C102_DEBUG_LEVEL 2 -#define SN9C102_MAX_DEVICES 64 -#define SN9C102_PRESERVE_IMGSCALE 0 -#define SN9C102_FORCE_MUNMAP 0 -#define SN9C102_MAX_FRAMES 32 -#define SN9C102_URBS 2 -#define SN9C102_ISO_PACKETS 7 -#define SN9C102_ALTERNATE_SETTING 8 -#define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS) -#define SN9C102_CTRL_TIMEOUT 300 -#define SN9C102_FRAME_TIMEOUT 0 - -/*****************************************************************************/ - -static const u8 SN9C102_Y_QTABLE0[64] = { - 8, 5, 5, 8, 12, 20, 25, 30, - 6, 6, 7, 9, 13, 29, 30, 27, - 7, 6, 8, 12, 20, 28, 34, 28, - 7, 8, 11, 14, 25, 43, 40, 31, - 9, 11, 18, 28, 34, 54, 51, 38, - 12, 17, 27, 32, 40, 52, 56, 46, - 24, 32, 39, 43, 51, 60, 60, 50, - 36, 46, 47, 49, 56, 50, 51, 49 -}; - -static const u8 SN9C102_UV_QTABLE0[64] = { - 8, 9, 12, 23, 49, 49, 49, 49, - 9, 10, 13, 33, 49, 49, 49, 49, - 12, 13, 28, 49, 49, 49, 49, 49, - 23, 33, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49 -}; - -static const u8 SN9C102_Y_QTABLE1[64] = { - 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 56, 68, 109, 103, 77, - 24, 35, 55, 64, 81, 104, 113, 92, - 49, 64, 78, 87, 103, 121, 120, 101, - 72, 92, 95, 98, 112, 100, 103, 99 -}; - -static const u8 SN9C102_UV_QTABLE1[64] = { - 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 -}; - -#endif /* _SN9C102_CONFIG_H_ */ diff --git a/drivers/staging/media/sn9c102/sn9c102_core.c b/drivers/staging/media/sn9c102/sn9c102_core.c deleted file mode 100644 index 98b30579b0ac..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_core.c +++ /dev/null @@ -1,3465 +0,0 @@ -/*************************************************************************** - * V4L2 driver for SN9C1xx PC Camera Controllers * - * * - * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/param.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/device.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/compiler.h> -#include <linux/ioctl.h> -#include <linux/poll.h> -#include <linux/stat.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <linux/version.h> -#include <linux/page-flags.h> -#include <asm/byteorder.h> -#include <asm/page.h> -#include <asm/uaccess.h> - -#include "sn9c102.h" - -/*****************************************************************************/ - -#define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers" -#define SN9C102_MODULE_ALIAS "sn9c1xx" -#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia" -#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" -#define SN9C102_MODULE_LICENSE "GPL" -#define SN9C102_MODULE_VERSION "1:1.48" - -/*****************************************************************************/ - -MODULE_DEVICE_TABLE(usb, sn9c102_id_table); - -MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL); -MODULE_DESCRIPTION(SN9C102_MODULE_NAME); -MODULE_ALIAS(SN9C102_MODULE_ALIAS); -MODULE_VERSION(SN9C102_MODULE_VERSION); -MODULE_LICENSE(SN9C102_MODULE_LICENSE); - -static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1}; -module_param_array(video_nr, short, NULL, 0444); -MODULE_PARM_DESC(video_nr, - " <-1|n[,...]>" - "\nSpecify V4L2 minor mode number." - "\n-1 = use next available (default)" - "\n n = use minor number n (integer >= 0)" - "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES) - " cameras this way." - "\nFor example:" - "\nvideo_nr=-1,2,-1 would assign minor number 2 to" - "\nthe second camera and use auto for the first" - "\none and for every other camera." - "\n"); - -static bool force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] = - SN9C102_FORCE_MUNMAP}; -module_param_array(force_munmap, bool, NULL, 0444); -MODULE_PARM_DESC(force_munmap, - " <0|1[,...]>" - "\nForce the application to unmap previously" - "\nmapped buffer memory before calling any VIDIOC_S_CROP or" - "\nVIDIOC_S_FMT ioctl's. Not all the applications support" - "\nthis feature. This parameter is specific for each" - "\ndetected camera." - "\n0 = do not force memory unmapping" - "\n1 = force memory unmapping (save memory)" - "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." - "\n"); - -static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] = - SN9C102_FRAME_TIMEOUT}; -module_param_array(frame_timeout, uint, NULL, 0644); -MODULE_PARM_DESC(frame_timeout, - " <0|n[,...]>" - "\nTimeout for a video frame in seconds before" - "\nreturning an I/O error; 0 for infinity." - "\nThis parameter is specific for each detected camera." - "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." - "\n"); - -#ifdef SN9C102_DEBUG -static unsigned short debug = SN9C102_DEBUG_LEVEL; -module_param(debug, ushort, 0644); -MODULE_PARM_DESC(debug, - " <n>" - "\nDebugging information level, from 0 to 3:" - "\n0 = none (use carefully)" - "\n1 = critical errors" - "\n2 = significant informations" - "\n3 = more verbose messages" - "\nLevel 3 is useful for testing only." - "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"." - "\n"); -#endif - -/* - Add the probe entries to this table. Be sure to add the entry in the right - place, since, on failure, the next probing routine is called according to - the order of the list below, from top to bottom. -*/ -static int (*sn9c102_sensor_table[])(struct sn9c102_device *) = { - &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ - &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */ - &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ - &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */ - &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */ - &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ - &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ - &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ - &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ - &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ - &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */ - &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ -}; - -/*****************************************************************************/ - -static u32 -sn9c102_request_buffers(struct sn9c102_device *cam, u32 count, - enum sn9c102_io_method io) -{ - struct v4l2_pix_format *p = &(cam->sensor.pix_format); - struct v4l2_rect *r = &(cam->sensor.cropcap.bounds); - size_t imagesize = cam->module_param.force_munmap || io == IO_READ ? - (p->width * p->height * p->priv) / 8 : - (r->width * r->height * p->priv) / 8; - void *buff = NULL; - u32 i; - - if (count > SN9C102_MAX_FRAMES) - count = SN9C102_MAX_FRAMES; - - if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120) - imagesize += 589 + 2; /* length of JPEG header + EOI marker */ - - cam->nbuffers = count; - while (cam->nbuffers > 0) { - buff = vmalloc_32_user(cam->nbuffers * PAGE_ALIGN(imagesize)); - if (buff) - break; - cam->nbuffers--; - } - - for (i = 0; i < cam->nbuffers; i++) { - cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); - cam->frame[i].buf.index = i; - cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); - cam->frame[i].buf.length = imagesize; - cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cam->frame[i].buf.sequence = 0; - cam->frame[i].buf.field = V4L2_FIELD_NONE; - cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; - cam->frame[i].buf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - } - - return cam->nbuffers; -} - - -static void sn9c102_release_buffers(struct sn9c102_device *cam) -{ - if (cam->nbuffers) { - vfree(cam->frame[0].bufmem); - cam->nbuffers = 0; - } - cam->frame_current = NULL; -} - - -static void sn9c102_empty_framequeues(struct sn9c102_device *cam) -{ - u32 i; - - INIT_LIST_HEAD(&cam->inqueue); - INIT_LIST_HEAD(&cam->outqueue); - - for (i = 0; i < SN9C102_MAX_FRAMES; i++) { - cam->frame[i].state = F_UNUSED; - cam->frame[i].buf.bytesused = 0; - } -} - - -static void sn9c102_requeue_outqueue(struct sn9c102_device *cam) -{ - struct sn9c102_frame_t *i; - - list_for_each_entry(i, &cam->outqueue, frame) { - i->state = F_QUEUED; - list_add(&i->frame, &cam->inqueue); - } - - INIT_LIST_HEAD(&cam->outqueue); -} - - -static void sn9c102_queue_unusedframes(struct sn9c102_device *cam) -{ - unsigned long lock_flags; - u32 i; - - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].state == F_UNUSED) { - cam->frame[i].state = F_QUEUED; - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_add_tail(&cam->frame[i].frame, &cam->inqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - } -} - -/*****************************************************************************/ - -/* - Write a sequence of count value/register pairs. Returns -1 after the first - failed write, or 0 for no errors. -*/ -int sn9c102_write_regs(struct sn9c102_device *cam, const u8 valreg[][2], - int count) -{ - struct usb_device *udev = cam->usbdev; - u8 *buff = cam->control_buffer; - int i, res; - - for (i = 0; i < count; i++) { - u8 index = valreg[i][1]; - - /* - index is a u8, so it must be <256 and can't be out of range. - If we put in a check anyway, gcc annoys us with a warning - hat our check is useless. People get all uppity when they - see warnings in the kernel compile. - */ - - *buff = valreg[i][0]; - - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, - 0x41, index, 0, buff, 1, - SN9C102_CTRL_TIMEOUT); - - if (res < 0) { - DBG(3, "Failed to write a register (value 0x%02X, " - "index 0x%02X, error %d)", *buff, index, res); - return -1; - } - - cam->reg[index] = *buff; - } - - return 0; -} - - -int sn9c102_write_reg(struct sn9c102_device *cam, u8 value, u16 index) -{ - struct usb_device *udev = cam->usbdev; - u8 *buff = cam->control_buffer; - int res; - - if (index >= ARRAY_SIZE(cam->reg)) - return -1; - - *buff = value; - - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); - if (res < 0) { - DBG(3, "Failed to write a register (value 0x%02X, index " - "0x%02X, error %d)", value, index, res); - return -1; - } - - cam->reg[index] = value; - - return 0; -} - - -/* NOTE: with the SN9C10[123] reading some registers always returns 0 */ -int sn9c102_read_reg(struct sn9c102_device *cam, u16 index) -{ - struct usb_device *udev = cam->usbdev; - u8 *buff = cam->control_buffer; - int res; - - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); - if (res < 0) - DBG(3, "Failed to read a register (index 0x%02X, error %d)", - index, res); - - return (res >= 0) ? (int)(*buff) : -1; -} - - -int sn9c102_pread_reg(struct sn9c102_device *cam, u16 index) -{ - if (index >= ARRAY_SIZE(cam->reg)) - return -1; - - return cam->reg[index]; -} - - -static int -sn9c102_i2c_wait(struct sn9c102_device *cam, - const struct sn9c102_sensor *sensor) -{ - int i, r; - - for (i = 1; i <= 5; i++) { - r = sn9c102_read_reg(cam, 0x08); - if (r < 0) - return -EIO; - if (r & 0x04) - return 0; - if (sensor->frequency & SN9C102_I2C_400KHZ) - udelay(5*16); - else - udelay(16*16); - } - return -EBUSY; -} - - -static int -sn9c102_i2c_detect_read_error(struct sn9c102_device *cam, - const struct sn9c102_sensor *sensor) -{ - int r , err = 0; - - r = sn9c102_read_reg(cam, 0x08); - if (r < 0) - err += r; - - if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { - if (!(r & 0x08)) - err += -1; - } else { - if (r & 0x08) - err += -1; - } - - return err ? -EIO : 0; -} - - -static int -sn9c102_i2c_detect_write_error(struct sn9c102_device *cam, - const struct sn9c102_sensor *sensor) -{ - int r; - - r = sn9c102_read_reg(cam, 0x08); - return (r < 0 || (r >= 0 && (r & 0x08))) ? -EIO : 0; -} - - -int -sn9c102_i2c_try_raw_read(struct sn9c102_device *cam, - const struct sn9c102_sensor *sensor, u8 data0, - u8 data1, u8 n, u8 buffer[]) -{ - struct usb_device *udev = cam->usbdev; - u8 *data = cam->control_buffer; - int i = 0, err = 0, res; - - /* Write cycle */ - data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | - ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10; - data[1] = data0; /* I2C slave id */ - data[2] = data1; /* address */ - data[7] = 0x10; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += sn9c102_i2c_wait(cam, sensor); - - /* Read cycle - n bytes */ - data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | - ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | - (n << 4) | 0x02; - data[1] = data0; - data[7] = 0x10; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += sn9c102_i2c_wait(cam, sensor); - - /* The first read byte will be placed in data[4] */ - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += sn9c102_i2c_detect_read_error(cam, sensor); - - PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1, - data[4]); - - if (err) { - DBG(3, "I2C read failed for %s image sensor", sensor->name); - return -1; - } - - if (buffer) - for (i = 0; i < n && i < 5; i++) - buffer[n-i-1] = data[4-i]; - - return (int)data[4]; -} - - -int -sn9c102_i2c_try_raw_write(struct sn9c102_device *cam, - const struct sn9c102_sensor *sensor, u8 n, u8 data0, - u8 data1, u8 data2, u8 data3, u8 data4, u8 data5) -{ - struct usb_device *udev = cam->usbdev; - u8 *data = cam->control_buffer; - int err = 0, res; - - /* Write cycle. It usually is address + value */ - data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | - ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) - | ((n - 1) << 4); - data[1] = data0; - data[2] = data1; - data[3] = data2; - data[4] = data3; - data[5] = data4; - data[6] = data5; - data[7] = 0x17; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += sn9c102_i2c_wait(cam, sensor); - err += sn9c102_i2c_detect_write_error(cam, sensor); - - if (err) - DBG(3, "I2C write failed for %s image sensor", sensor->name); - - PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, " - "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X", - n, data0, data1, data2, data3, data4, data5); - - return err ? -1 : 0; -} - - -int -sn9c102_i2c_try_read(struct sn9c102_device *cam, - const struct sn9c102_sensor *sensor, u8 address) -{ - return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id, - address, 1, NULL); -} - - -static int sn9c102_i2c_try_write(struct sn9c102_device *cam, - const struct sn9c102_sensor *sensor, - u8 address, u8 value) -{ - return sn9c102_i2c_try_raw_write(cam, sensor, 3, - sensor->i2c_slave_id, address, - value, 0, 0, 0); -} - - -int sn9c102_i2c_read(struct sn9c102_device *cam, u8 address) -{ - return sn9c102_i2c_try_read(cam, &cam->sensor, address); -} - - -int sn9c102_i2c_write(struct sn9c102_device *cam, u8 address, u8 value) -{ - return sn9c102_i2c_try_write(cam, &cam->sensor, address, value); -} - -/*****************************************************************************/ - -static size_t sn9c102_sof_length(struct sn9c102_device *cam) -{ - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - return 12; - case BRIDGE_SN9C103: - return 18; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - return 62; - } - - return 0; -} - - -static void* -sn9c102_find_sof_header(struct sn9c102_device *cam, void *mem, size_t len) -{ - static const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; - const char *m = mem; - size_t soflen = 0, i, j; - - soflen = sn9c102_sof_length(cam); - - for (i = 0; i < len; i++) { - size_t b; - - /* Read the variable part of the header */ - if (unlikely(cam->sof.bytesread >= sizeof(marker))) { - cam->sof.header[cam->sof.bytesread] = *(m+i); - if (++cam->sof.bytesread == soflen) { - cam->sof.bytesread = 0; - return mem + i; - } - continue; - } - - /* Search for the SOF marker (fixed part) in the header */ - for (j = 0, b = cam->sof.bytesread; j+b < sizeof(marker); j++) { - if (unlikely(i+j == len)) - return NULL; - if (*(m+i+j) == marker[cam->sof.bytesread]) { - cam->sof.header[cam->sof.bytesread] = *(m+i+j); - if (++cam->sof.bytesread == sizeof(marker)) { - PDBGG("Bytes to analyze: %zd. SOF " - "starts at byte #%zd", len, i); - i += j+1; - break; - } - } else { - cam->sof.bytesread = 0; - break; - } - } - } - - return NULL; -} - - -static void* -sn9c102_find_eof_header(struct sn9c102_device *cam, void *mem, size_t len) -{ - static const u8 eof_header[4][4] = { - {0x00, 0x00, 0x00, 0x00}, - {0x40, 0x00, 0x00, 0x00}, - {0x80, 0x00, 0x00, 0x00}, - {0xc0, 0x00, 0x00, 0x00}, - }; - size_t i, j; - - /* The EOF header does not exist in compressed data */ - if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X || - cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) - return NULL; - - /* - The EOF header might cross the packet boundary, but this is not a - problem, since the end of a frame is determined by checking its size - in the first place. - */ - for (i = 0; (len >= 4) && (i <= len - 4); i++) - for (j = 0; j < ARRAY_SIZE(eof_header); j++) - if (!memcmp(mem + i, eof_header[j], 4)) - return mem + i; - - return NULL; -} - - -static void -sn9c102_write_jpegheader(struct sn9c102_device *cam, struct sn9c102_frame_t *f) -{ - static const u8 jpeg_header[589] = { - 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05, - 0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06, - 0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e, - 0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16, - 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16, - 0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29, - 0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29, - 0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a, - 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2, - 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, - 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, - 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, - 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, - 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, - 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, - 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, - 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, - 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, - 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, - 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, - 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, - 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, - 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, - 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, - 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, - 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, - 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02, - 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, - 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, - 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, - 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, - 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, - 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, - 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, - 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, - 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, - 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, - 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, - 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, - 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, - 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11, - 0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, - 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, - 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 - }; - u8 *pos = f->bufmem; - - memcpy(pos, jpeg_header, sizeof(jpeg_header)); - *(pos + 6) = 0x00; - *(pos + 7 + 64) = 0x01; - if (cam->compression.quality == 0) { - memcpy(pos + 7, SN9C102_Y_QTABLE0, 64); - memcpy(pos + 8 + 64, SN9C102_UV_QTABLE0, 64); - } else if (cam->compression.quality == 1) { - memcpy(pos + 7, SN9C102_Y_QTABLE1, 64); - memcpy(pos + 8 + 64, SN9C102_UV_QTABLE1, 64); - } - *(pos + 564) = cam->sensor.pix_format.width & 0xFF; - *(pos + 563) = (cam->sensor.pix_format.width >> 8) & 0xFF; - *(pos + 562) = cam->sensor.pix_format.height & 0xFF; - *(pos + 561) = (cam->sensor.pix_format.height >> 8) & 0xFF; - *(pos + 567) = 0x21; - - f->buf.bytesused += sizeof(jpeg_header); -} - - -static void sn9c102_urb_complete(struct urb *urb) -{ - struct sn9c102_device *cam = urb->context; - struct sn9c102_frame_t **f; - size_t imagesize, soflen; - u8 i; - int err = 0; - - if (urb->status == -ENOENT) - return; - - f = &cam->frame_current; - - if (cam->stream == STREAM_INTERRUPT) { - cam->stream = STREAM_OFF; - if ((*f)) - (*f)->state = F_QUEUED; - cam->sof.bytesread = 0; - DBG(3, "Stream interrupted by application"); - wake_up(&cam->wait_stream); - } - - if (cam->state & DEV_DISCONNECTED) - return; - - if (cam->state & DEV_MISCONFIGURED) { - wake_up_interruptible(&cam->wait_frame); - return; - } - - if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue)) - goto resubmit_urb; - - if (!(*f)) - (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t, - frame); - - imagesize = (cam->sensor.pix_format.width * - cam->sensor.pix_format.height * - cam->sensor.pix_format.priv) / 8; - if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) - imagesize += 589; /* length of jpeg header */ - soflen = sn9c102_sof_length(cam); - - for (i = 0; i < urb->number_of_packets; i++) { - unsigned int img, len, status; - void *pos, *sof, *eof; - - len = urb->iso_frame_desc[i].actual_length; - status = urb->iso_frame_desc[i].status; - pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; - - if (status) { - DBG(3, "Error in isochronous frame"); - (*f)->state = F_ERROR; - cam->sof.bytesread = 0; - continue; - } - - PDBGG("Isochrnous frame: length %u, #%u i", len, i); - -redo: - sof = sn9c102_find_sof_header(cam, pos, len); - if (likely(!sof)) { - eof = sn9c102_find_eof_header(cam, pos, len); - if ((*f)->state == F_GRABBING) { -end_of_frame: - img = len; - - if (eof) - img = (eof > pos) ? eof - pos - 1 : 0; - - if ((*f)->buf.bytesused + img > imagesize) { - u32 b; - b = (*f)->buf.bytesused + img - - imagesize; - img = imagesize - (*f)->buf.bytesused; - PDBGG("Expected EOF not found: video " - "frame cut"); - if (eof) - DBG(3, "Exceeded limit: +%u " - "bytes", (unsigned)(b)); - } - - memcpy((*f)->bufmem + (*f)->buf.bytesused, pos, - img); - - if ((*f)->buf.bytesused == 0) - v4l2_get_timestamp( - &(*f)->buf.timestamp); - - (*f)->buf.bytesused += img; - - if ((*f)->buf.bytesused == imagesize || - ((cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_SN9C10X || - cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_JPEG) && eof)) { - u32 b; - - b = (*f)->buf.bytesused; - (*f)->state = F_DONE; - (*f)->buf.sequence = ++cam->frame_count; - - spin_lock(&cam->queue_lock); - list_move_tail(&(*f)->frame, - &cam->outqueue); - if (!list_empty(&cam->inqueue)) - (*f) = list_entry( - cam->inqueue.next, - struct sn9c102_frame_t, - frame); - else - (*f) = NULL; - spin_unlock(&cam->queue_lock); - - memcpy(cam->sysfs.frame_header, - cam->sof.header, soflen); - - DBG(3, "Video frame captured: %lu " - "bytes", (unsigned long)(b)); - - if (!(*f)) - goto resubmit_urb; - - } else if (eof) { - (*f)->state = F_ERROR; - DBG(3, "Not expected EOF after %lu " - "bytes of image data", - (unsigned long) - ((*f)->buf.bytesused)); - } - - if (sof) /* (1) */ - goto start_of_frame; - - } else if (eof) { - DBG(3, "EOF without SOF"); - continue; - - } else { - PDBGG("Ignoring pointless isochronous frame"); - continue; - } - - } else if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) { -start_of_frame: - (*f)->state = F_GRABBING; - (*f)->buf.bytesused = 0; - len -= (sof - pos); - pos = sof; - if (cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_JPEG) - sn9c102_write_jpegheader(cam, (*f)); - DBG(3, "SOF detected: new video frame"); - if (len) - goto redo; - - } else if ((*f)->state == F_GRABBING) { - eof = sn9c102_find_eof_header(cam, pos, len); - if (eof && eof < sof) - goto end_of_frame; /* (1) */ - else { - if (cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_SN9C10X || - cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_JPEG) { - if (sof - pos >= soflen) { - eof = sof - soflen; - } else { /* remove header */ - eof = pos; - (*f)->buf.bytesused -= - (soflen - (sof - pos)); - } - goto end_of_frame; - } else { - DBG(3, "SOF before expected EOF after " - "%lu bytes of image data", - (unsigned long) - ((*f)->buf.bytesused)); - goto start_of_frame; - } - } - } - } - -resubmit_urb: - urb->dev = cam->usbdev; - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err < 0 && err != -EPERM) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "usb_submit_urb() failed"); - } - - wake_up_interruptible(&cam->wait_frame); -} - - -static int sn9c102_start_transfer(struct sn9c102_device *cam) -{ - struct usb_device *udev = cam->usbdev; - struct urb *urb; - struct usb_host_interface *altsetting = usb_altnum_to_altsetting( - usb_ifnum_to_if(udev, 0), - SN9C102_ALTERNATE_SETTING); - const unsigned int psz = le16_to_cpu(altsetting-> - endpoint[0].desc.wMaxPacketSize); - s8 i, j; - int err = 0; - - for (i = 0; i < SN9C102_URBS; i++) { - cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz, - GFP_KERNEL); - if (!cam->transfer_buffer[i]) { - err = -ENOMEM; - DBG(1, "Not enough memory"); - goto free_buffers; - } - } - - for (i = 0; i < SN9C102_URBS; i++) { - urb = usb_alloc_urb(SN9C102_ISO_PACKETS, GFP_KERNEL); - cam->urb[i] = urb; - if (!urb) { - err = -ENOMEM; - DBG(1, "usb_alloc_urb() failed"); - goto free_urbs; - } - urb->dev = udev; - urb->context = cam; - urb->pipe = usb_rcvisocpipe(udev, 1); - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = SN9C102_ISO_PACKETS; - urb->complete = sn9c102_urb_complete; - urb->transfer_buffer = cam->transfer_buffer[i]; - urb->transfer_buffer_length = psz * SN9C102_ISO_PACKETS; - urb->interval = 1; - for (j = 0; j < SN9C102_ISO_PACKETS; j++) { - urb->iso_frame_desc[j].offset = psz * j; - urb->iso_frame_desc[j].length = psz; - } - } - - /* Enable video */ - if (!(cam->reg[0x01] & 0x04)) { - err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01); - if (err) { - err = -EIO; - DBG(1, "I/O hardware error"); - goto free_urbs; - } - } - - err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING); - if (err) { - DBG(1, "usb_set_interface() failed"); - goto free_urbs; - } - - cam->frame_current = NULL; - cam->sof.bytesread = 0; - - for (i = 0; i < SN9C102_URBS; i++) { - err = usb_submit_urb(cam->urb[i], GFP_KERNEL); - if (err) { - for (j = i-1; j >= 0; j--) - usb_kill_urb(cam->urb[j]); - DBG(1, "usb_submit_urb() failed, error %d", err); - goto free_urbs; - } - } - - return 0; - -free_urbs: - for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++) - usb_free_urb(cam->urb[i]); - -free_buffers: - for (i = 0; (i < SN9C102_URBS) && cam->transfer_buffer[i]; i++) - kfree(cam->transfer_buffer[i]); - - return err; -} - - -static int sn9c102_stop_transfer(struct sn9c102_device *cam) -{ - struct usb_device *udev = cam->usbdev; - s8 i; - int err = 0; - - if (cam->state & DEV_DISCONNECTED) - return 0; - - for (i = SN9C102_URBS-1; i >= 0; i--) { - usb_kill_urb(cam->urb[i]); - usb_free_urb(cam->urb[i]); - kfree(cam->transfer_buffer[i]); - } - - err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */ - if (err) - DBG(3, "usb_set_interface() failed"); - - return err; -} - - -static int sn9c102_stream_interrupt(struct sn9c102_device *cam) -{ - cam->stream = STREAM_INTERRUPT; - wait_event_timeout(cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED), - SN9C102_URB_TIMEOUT); - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - else if (cam->stream != STREAM_OFF) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "URB timeout reached. The camera is misconfigured. " - "To use it, close and open %s again.", - video_device_node_name(cam->v4ldev)); - return -EIO; - } - - return 0; -} - -/*****************************************************************************/ - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static u16 sn9c102_strtou16(const char *buff, size_t len, ssize_t *count) -{ - char str[7]; - char *endp; - unsigned long val; - - if (len < 6) { - strncpy(str, buff, len); - str[len] = '\0'; - } else { - strncpy(str, buff, 6); - str[6] = '\0'; - } - - val = simple_strtoul(str, &endp, 0); - - *count = 0; - if (val <= 0xffff) - *count = (ssize_t)(endp - str); - if ((*count) && (len == *count+1) && (buff[*count] == '\n')) - *count += 1; - - return (u16)val; -} - -/* - NOTE 1: being inside one of the following methods implies that the v4l - device exists for sure (see kobjects and reference counters) - NOTE 2: buffers are PAGE_SIZE long -*/ - -static ssize_t sn9c102_show_reg(struct device *cd, - struct device_attribute *attr, char *buf) -{ - struct sn9c102_device *cam; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - count = sprintf(buf, "%u\n", cam->sysfs.reg); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_reg(struct device *cd, struct device_attribute *attr, - const char *buf, size_t len) -{ - struct sn9c102_device *cam; - u16 index; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - index = sn9c102_strtou16(buf, len, &count); - if (index >= ARRAY_SIZE(cam->reg) || !count) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - cam->sysfs.reg = index; - - DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t sn9c102_show_val(struct device *cd, - struct device_attribute *attr, char *buf) -{ - struct sn9c102_device *cam; - ssize_t count; - int val; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - val = sn9c102_read_reg(cam, cam->sysfs.reg); - if (val < 0) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - - count = sprintf(buf, "%d\n", val); - - DBG(3, "Read bytes: %zd, value: %d", count, val); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_val(struct device *cd, struct device_attribute *attr, - const char *buf, size_t len) -{ - struct sn9c102_device *cam; - u16 value; - ssize_t count; - int err; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - value = sn9c102_strtou16(buf, len, &count); - if (!count) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - err = sn9c102_write_reg(cam, value, cam->sysfs.reg); - if (err) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - - DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X", - cam->sysfs.reg, value); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t sn9c102_show_i2c_reg(struct device *cd, - struct device_attribute *attr, char *buf) -{ - struct sn9c102_device *cam; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg); - - DBG(3, "Read bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_i2c_reg(struct device *cd, struct device_attribute *attr, - const char *buf, size_t len) -{ - struct sn9c102_device *cam; - u16 index; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - index = sn9c102_strtou16(buf, len, &count); - if (!count) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - cam->sysfs.i2c_reg = index; - - DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t sn9c102_show_i2c_val(struct device *cd, - struct device_attribute *attr, char *buf) -{ - struct sn9c102_device *cam; - ssize_t count; - int val; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENOSYS; - } - - val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg); - if (val < 0) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - - count = sprintf(buf, "%d\n", val); - - DBG(3, "Read bytes: %zd, value: %d", count, val); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_i2c_val(struct device *cd, struct device_attribute *attr, - const char *buf, size_t len) -{ - struct sn9c102_device *cam; - u16 value; - ssize_t count; - int err; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENOSYS; - } - - value = sn9c102_strtou16(buf, len, &count); - if (!count) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value); - if (err) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - - DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X", - cam->sysfs.i2c_reg, value); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_green(struct device *cd, struct device_attribute *attr, - const char *buf, size_t len) -{ - struct sn9c102_device *cam; - enum sn9c102_bridge bridge; - ssize_t res = 0; - u16 value; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - bridge = cam->bridge; - - mutex_unlock(&sn9c102_sysfs_lock); - - value = sn9c102_strtou16(buf, len, &count); - if (!count) - return -EINVAL; - - switch (bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - if (value > 0x0f) - return -EINVAL; - res = sn9c102_store_reg(cd, attr, "0x11", 4); - if (res >= 0) - res = sn9c102_store_val(cd, attr, buf, len); - break; - case BRIDGE_SN9C103: - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - if (value > 0x7f) - return -EINVAL; - res = sn9c102_store_reg(cd, attr, "0x07", 4); - if (res >= 0) - res = sn9c102_store_val(cd, attr, buf, len); - break; - } - - return res; -} - - -static ssize_t -sn9c102_store_blue(struct device *cd, struct device_attribute *attr, - const char *buf, size_t len) -{ - ssize_t res = 0; - u16 value; - ssize_t count; - - value = sn9c102_strtou16(buf, len, &count); - if (!count || value > 0x7f) - return -EINVAL; - - res = sn9c102_store_reg(cd, attr, "0x06", 4); - if (res >= 0) - res = sn9c102_store_val(cd, attr, buf, len); - - return res; -} - - -static ssize_t -sn9c102_store_red(struct device *cd, struct device_attribute *attr, - const char *buf, size_t len) -{ - ssize_t res = 0; - u16 value; - ssize_t count; - - value = sn9c102_strtou16(buf, len, &count); - if (!count || value > 0x7f) - return -EINVAL; - res = sn9c102_store_reg(cd, attr, "0x05", 4); - if (res >= 0) - res = sn9c102_store_val(cd, attr, buf, len); - - return res; -} - - -static ssize_t sn9c102_show_frame_header(struct device *cd, - struct device_attribute *attr, - char *buf) -{ - struct sn9c102_device *cam; - ssize_t count; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) - return -ENODEV; - - count = sizeof(cam->sysfs.frame_header); - memcpy(buf, cam->sysfs.frame_header, count); - - DBG(3, "Frame header, read bytes: %zd", count); - - return count; -} - - -static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, sn9c102_show_reg, sn9c102_store_reg); -static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, sn9c102_show_val, sn9c102_store_val); -static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, - sn9c102_show_i2c_reg, sn9c102_store_i2c_reg); -static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, - sn9c102_show_i2c_val, sn9c102_store_i2c_val); -static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green); -static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue); -static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red); -static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL); - - -static int sn9c102_create_sysfs(struct sn9c102_device *cam) -{ - struct device *dev = &(cam->v4ldev->dev); - int err = 0; - - err = device_create_file(dev, &dev_attr_reg); - if (err) - goto err_out; - err = device_create_file(dev, &dev_attr_val); - if (err) - goto err_reg; - err = device_create_file(dev, &dev_attr_frame_header); - if (err) - goto err_val; - - if (cam->sensor.sysfs_ops) { - err = device_create_file(dev, &dev_attr_i2c_reg); - if (err) - goto err_frame_header; - err = device_create_file(dev, &dev_attr_i2c_val); - if (err) - goto err_i2c_reg; - } - - if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { - err = device_create_file(dev, &dev_attr_green); - if (err) - goto err_i2c_val; - } else { - err = device_create_file(dev, &dev_attr_blue); - if (err) - goto err_i2c_val; - err = device_create_file(dev, &dev_attr_red); - if (err) - goto err_blue; - } - - return 0; - -err_blue: - device_remove_file(dev, &dev_attr_blue); -err_i2c_val: - if (cam->sensor.sysfs_ops) - device_remove_file(dev, &dev_attr_i2c_val); -err_i2c_reg: - if (cam->sensor.sysfs_ops) - device_remove_file(dev, &dev_attr_i2c_reg); -err_frame_header: - device_remove_file(dev, &dev_attr_frame_header); -err_val: - device_remove_file(dev, &dev_attr_val); -err_reg: - device_remove_file(dev, &dev_attr_reg); -err_out: - return err; -} -#endif /* CONFIG_VIDEO_ADV_DEBUG */ - -/*****************************************************************************/ - -static int -sn9c102_set_pix_format(struct sn9c102_device *cam, struct v4l2_pix_format *pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X || - pix->pixelformat == V4L2_PIX_FMT_JPEG) { - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, - 0x18); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, - 0x18); - break; - } - } else { - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, - 0x18); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, - 0x18); - break; - } - } - - return err ? -EIO : 0; -} - - -static int -sn9c102_set_compression(struct sn9c102_device *cam, - struct v4l2_jpegcompression *compression) -{ - int i, err = 0; - - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - if (compression->quality == 0) - err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, - 0x17); - else if (compression->quality == 1) - err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, - 0x17); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - if (compression->quality == 0) { - for (i = 0; i <= 63; i++) { - err += sn9c102_write_reg(cam, - SN9C102_Y_QTABLE1[i], - 0x100 + i); - err += sn9c102_write_reg(cam, - SN9C102_UV_QTABLE1[i], - 0x140 + i); - } - err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf, - 0x18); - } else if (compression->quality == 1) { - for (i = 0; i <= 63; i++) { - err += sn9c102_write_reg(cam, - SN9C102_Y_QTABLE1[i], - 0x100 + i); - err += sn9c102_write_reg(cam, - SN9C102_UV_QTABLE1[i], - 0x140 + i); - } - err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x40, - 0x18); - } - break; - } - - return err ? -EIO : 0; -} - - -static int sn9c102_set_scale(struct sn9c102_device *cam, u8 scale) -{ - u8 r = 0; - int err = 0; - - if (scale == 1) - r = cam->reg[0x18] & 0xcf; - else if (scale == 2) { - r = cam->reg[0x18] & 0xcf; - r |= 0x10; - } else if (scale == 4) - r = cam->reg[0x18] | 0x20; - - err += sn9c102_write_reg(cam, r, 0x18); - if (err) - return -EIO; - - PDBGG("Scaling factor: %u", scale); - - return 0; -} - - -static int sn9c102_set_crop(struct sn9c102_device *cam, struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = &cam->sensor; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left), - v_start = (u8)(rect->top - s->cropcap.bounds.top), - h_size = (u8)(rect->width / 16), - v_size = (u8)(rect->height / 16); - int err = 0; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - err += sn9c102_write_reg(cam, h_size, 0x15); - err += sn9c102_write_reg(cam, v_size, 0x16); - if (err) - return -EIO; - - PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size " - "%u %u %u %u", h_start, v_start, h_size, v_size); - - return 0; -} - - -static int sn9c102_init(struct sn9c102_device *cam) -{ - struct sn9c102_sensor *s = &cam->sensor; - struct v4l2_control ctrl; - struct v4l2_queryctrl *qctrl; - struct v4l2_rect *rect; - u8 i = 0; - int err = 0; - - if (!(cam->state & DEV_INITIALIZED)) { - mutex_init(&cam->open_mutex); - init_waitqueue_head(&cam->wait_open); - qctrl = s->qctrl; - rect = &(s->cropcap.defrect); - } else { /* use current values */ - qctrl = s->_qctrl; - rect = &(s->_rect); - } - - err += sn9c102_set_scale(cam, rect->width / s->pix_format.width); - err += sn9c102_set_crop(cam, rect); - if (err) - return err; - - if (s->init) { - err = s->init(cam); - if (err) { - DBG(3, "Sensor initialization failed"); - return err; - } - } - - if (!(cam->state & DEV_INITIALIZED)) - if (cam->bridge == BRIDGE_SN9C101 || - cam->bridge == BRIDGE_SN9C102 || - cam->bridge == BRIDGE_SN9C103) { - if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG) - s->pix_format.pixelformat = V4L2_PIX_FMT_SBGGR8; - cam->compression.quality = cam->reg[0x17] & 0x01 ? - 0 : 1; - } else { - if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) - s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG; - cam->compression.quality = cam->reg[0x18] & 0x40 ? - 0 : 1; - err += sn9c102_set_compression(cam, &cam->compression); - } - else - err += sn9c102_set_compression(cam, &cam->compression); - err += sn9c102_set_pix_format(cam, &s->pix_format); - if (s->set_pix_format) - err += s->set_pix_format(cam, &s->pix_format); - if (err) - return err; - - if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X || - s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG) - DBG(3, "Compressed video format is active, quality %d", - cam->compression.quality); - else - DBG(3, "Uncompressed video format is active"); - - if (s->set_crop) { - err = s->set_crop(cam, rect); - if (err) { - DBG(3, "set_crop() failed"); - return err; - } - } - - if (s->set_ctrl) { - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (s->qctrl[i].id != 0 && - !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) { - ctrl.id = s->qctrl[i].id; - ctrl.value = qctrl[i].default_value; - err = s->set_ctrl(cam, &ctrl); - if (err) { - DBG(3, "Set %s control failed", - s->qctrl[i].name); - return err; - } - DBG(3, "Image sensor supports '%s' control", - s->qctrl[i].name); - } - } - - if (!(cam->state & DEV_INITIALIZED)) { - mutex_init(&cam->fileop_mutex); - spin_lock_init(&cam->queue_lock); - init_waitqueue_head(&cam->wait_frame); - init_waitqueue_head(&cam->wait_stream); - cam->nreadbuffers = 2; - memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); - memcpy(&(s->_rect), &(s->cropcap.defrect), - sizeof(struct v4l2_rect)); - cam->state |= DEV_INITIALIZED; - } - - DBG(2, "Initialization succeeded"); - return 0; -} - -/*****************************************************************************/ - -static void sn9c102_release_resources(struct kref *kref) -{ - struct sn9c102_device *cam; - - mutex_lock(&sn9c102_sysfs_lock); - - cam = container_of(kref, struct sn9c102_device, kref); - - DBG(2, "V4L2 device %s deregistered", - video_device_node_name(cam->v4ldev)); - video_set_drvdata(cam->v4ldev, NULL); - video_unregister_device(cam->v4ldev); - v4l2_device_unregister(&cam->v4l2_dev); - usb_put_dev(cam->usbdev); - kfree(cam->control_buffer); - kfree(cam); - - mutex_unlock(&sn9c102_sysfs_lock); - -} - - -static int sn9c102_open(struct file *filp) -{ - struct sn9c102_device *cam; - int err = 0; - - /* - A read_trylock() in open() is the only safe way to prevent race - conditions with disconnect(), one close() and multiple (not - necessarily simultaneous) attempts to open(). For example, it - prevents from waiting for a second access, while the device - structure is being deallocated, after a possible disconnect() and - during a following close() holding the write lock: given that, after - this deallocation, no access will be possible anymore, using the - non-trylock version would have let open() gain the access to the - device structure improperly. - For this reason the lock must also not be per-device. - */ - if (!down_read_trylock(&sn9c102_dev_lock)) - return -ERESTARTSYS; - - cam = video_drvdata(filp); - - if (wait_for_completion_interruptible(&cam->probe)) { - up_read(&sn9c102_dev_lock); - return -ERESTARTSYS; - } - - kref_get(&cam->kref); - - /* - Make sure to isolate all the simultaneous opens. - */ - if (mutex_lock_interruptible(&cam->open_mutex)) { - kref_put(&cam->kref, sn9c102_release_resources); - up_read(&sn9c102_dev_lock); - return -ERESTARTSYS; - } - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - err = -ENODEV; - goto out; - } - - if (cam->users) { - DBG(2, "Device %s is already in use", - video_device_node_name(cam->v4ldev)); - DBG(3, "Simultaneous opens are not supported"); - /* - open() must follow the open flags and should block - eventually while the device is in use. - */ - if ((filp->f_flags & O_NONBLOCK) || - (filp->f_flags & O_NDELAY)) { - err = -EWOULDBLOCK; - goto out; - } - DBG(2, "A blocking open() has been requested. Wait for the " - "device to be released..."); - up_read(&sn9c102_dev_lock); - /* - We will not release the "open_mutex" lock, so that only one - process can be in the wait queue below. This way the process - will be sleeping while holding the lock, without losing its - priority after any wake_up(). - */ - err = wait_event_interruptible_exclusive(cam->wait_open, - (cam->state & DEV_DISCONNECTED) - || !cam->users); - down_read(&sn9c102_dev_lock); - if (err) - goto out; - if (cam->state & DEV_DISCONNECTED) { - err = -ENODEV; - goto out; - } - } - - if (cam->state & DEV_MISCONFIGURED) { - err = sn9c102_init(cam); - if (err) { - DBG(1, "Initialization failed again. " - "I will retry on next open()."); - goto out; - } - cam->state &= ~DEV_MISCONFIGURED; - } - - err = sn9c102_start_transfer(cam); - if (err) - goto out; - - filp->private_data = cam; - cam->users++; - cam->io = IO_NONE; - cam->stream = STREAM_OFF; - cam->nbuffers = 0; - cam->frame_count = 0; - sn9c102_empty_framequeues(cam); - - DBG(3, "Video device %s is open", video_device_node_name(cam->v4ldev)); - -out: - mutex_unlock(&cam->open_mutex); - if (err) - kref_put(&cam->kref, sn9c102_release_resources); - - up_read(&sn9c102_dev_lock); - return err; -} - - -static int sn9c102_release(struct file *filp) -{ - struct sn9c102_device *cam; - - down_write(&sn9c102_dev_lock); - - cam = video_drvdata(filp); - - sn9c102_stop_transfer(cam); - sn9c102_release_buffers(cam); - cam->users--; - wake_up_interruptible_nr(&cam->wait_open, 1); - - DBG(3, "Video device %s closed", video_device_node_name(cam->v4ldev)); - - kref_put(&cam->kref, sn9c102_release_resources); - - up_write(&sn9c102_dev_lock); - - return 0; -} - - -static ssize_t -sn9c102_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) -{ - struct sn9c102_device *cam = video_drvdata(filp); - struct sn9c102_frame_t *f, *i; - unsigned long lock_flags; - long timeout; - int err = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (cam->io == IO_MMAP) { - DBG(3, "Close and open the device again to choose " - "the read method"); - mutex_unlock(&cam->fileop_mutex); - return -EBUSY; - } - - if (cam->io == IO_NONE) { - if (!sn9c102_request_buffers(cam, cam->nreadbuffers, IO_READ)) { - DBG(1, "read() failed, not enough memory"); - mutex_unlock(&cam->fileop_mutex); - return -ENOMEM; - } - cam->io = IO_READ; - cam->stream = STREAM_ON; - } - - if (list_empty(&cam->inqueue)) { - if (!list_empty(&cam->outqueue)) - sn9c102_empty_framequeues(cam); - sn9c102_queue_unusedframes(cam); - } - - if (!count) { - mutex_unlock(&cam->fileop_mutex); - return 0; - } - - if (list_empty(&cam->outqueue)) { - if (filp->f_flags & O_NONBLOCK) { - mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } - if (!cam->module_param.frame_timeout) { - err = wait_event_interruptible - (cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED)); - if (err) { - mutex_unlock(&cam->fileop_mutex); - return err; - } - } else { - timeout = wait_event_interruptible_timeout - (cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - msecs_to_jiffies( - cam->module_param.frame_timeout * 1000 - ) - ); - if (timeout < 0) { - mutex_unlock(&cam->fileop_mutex); - return timeout; - } else if (timeout == 0 && - !(cam->state & DEV_DISCONNECTED)) { - DBG(1, "Video frame timeout elapsed"); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - } - if (cam->state & DEV_DISCONNECTED) { - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - if (cam->state & DEV_MISCONFIGURED) { - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - } - - f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame); - - if (count > f->buf.bytesused) - count = f->buf.bytesused; - - if (copy_to_user(buf, f->bufmem, count)) { - err = -EFAULT; - goto exit; - } - *f_pos += count; - -exit: - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_for_each_entry(i, &cam->outqueue, frame) - i->state = F_UNUSED; - INIT_LIST_HEAD(&cam->outqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - sn9c102_queue_unusedframes(cam); - - PDBGG("Frame #%lu, bytes read: %zu", - (unsigned long)f->buf.index, count); - - mutex_unlock(&cam->fileop_mutex); - - return count; -} - - -static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) -{ - struct sn9c102_device *cam = video_drvdata(filp); - struct sn9c102_frame_t *f; - unsigned long lock_flags; - unsigned int mask = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return POLLERR; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - goto error; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - goto error; - } - - if (cam->io == IO_NONE) { - if (!sn9c102_request_buffers(cam, cam->nreadbuffers, - IO_READ)) { - DBG(1, "poll() failed, not enough memory"); - goto error; - } - cam->io = IO_READ; - cam->stream = STREAM_ON; - } - - if (cam->io == IO_READ) { - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_for_each_entry(f, &cam->outqueue, frame) - f->state = F_UNUSED; - INIT_LIST_HEAD(&cam->outqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - sn9c102_queue_unusedframes(cam); - } - - poll_wait(filp, &cam->wait_frame, wait); - - if (!list_empty(&cam->outqueue)) - mask |= POLLIN | POLLRDNORM; - - mutex_unlock(&cam->fileop_mutex); - - return mask; - -error: - mutex_unlock(&cam->fileop_mutex); - return POLLERR; -} - - -static void sn9c102_vm_open(struct vm_area_struct *vma) -{ - struct sn9c102_frame_t *f = vma->vm_private_data; - f->vma_use_count++; -} - - -static void sn9c102_vm_close(struct vm_area_struct *vma) -{ - /* NOTE: buffers are not freed here */ - struct sn9c102_frame_t *f = vma->vm_private_data; - f->vma_use_count--; -} - - -static const struct vm_operations_struct sn9c102_vm_ops = { - .open = sn9c102_vm_open, - .close = sn9c102_vm_close, -}; - - -static int sn9c102_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct sn9c102_device *cam = video_drvdata(filp); - unsigned long size = vma->vm_end - vma->vm_start, - start = vma->vm_start; - void *pos; - u32 i; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (!(vma->vm_flags & (VM_WRITE | VM_READ))) { - mutex_unlock(&cam->fileop_mutex); - return -EACCES; - } - - if (cam->io != IO_MMAP || - size != PAGE_ALIGN(cam->frame[0].buf.length)) { - mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - - for (i = 0; i < cam->nbuffers; i++) { - if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff) - break; - } - if (i == cam->nbuffers) { - mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - - vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; - - pos = cam->frame[i].bufmem; - while (size > 0) { /* size is page-aligned */ - if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { - mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - size -= PAGE_SIZE; - } - - vma->vm_ops = &sn9c102_vm_ops; - vma->vm_private_data = &cam->frame[i]; - sn9c102_vm_open(vma); - - mutex_unlock(&cam->fileop_mutex); - - return 0; -} - -/*****************************************************************************/ - -static int -sn9c102_vidioc_querycap(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_capability cap = { - .driver = "sn9c102", - .version = LINUX_VERSION_CODE, - .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING, - }; - - strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); - if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) - strlcpy(cap.bus_info, dev_name(&cam->usbdev->dev), - sizeof(cap.bus_info)); - - if (copy_to_user(arg, &cap, sizeof(cap))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_enuminput(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_input i; - - if (copy_from_user(&i, arg, sizeof(i))) - return -EFAULT; - - if (i.index) - return -EINVAL; - - memset(&i, 0, sizeof(i)); - strcpy(i.name, "Camera"); - i.type = V4L2_INPUT_TYPE_CAMERA; - i.capabilities = V4L2_IN_CAP_STD; - - if (copy_to_user(arg, &i, sizeof(i))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_g_input(struct sn9c102_device *cam, void __user *arg) -{ - int index = 0; - - if (copy_to_user(arg, &index, sizeof(index))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_input(struct sn9c102_device *cam, void __user *arg) -{ - int index; - - if (copy_from_user(&index, arg, sizeof(index))) - return -EFAULT; - - if (index != 0) - return -EINVAL; - - return 0; -} - - -static int -sn9c102_vidioc_query_ctrl(struct sn9c102_device *cam, void __user *arg) -{ - struct sn9c102_sensor *s = &cam->sensor; - struct v4l2_queryctrl qc; - u8 i; - - if (copy_from_user(&qc, arg, sizeof(qc))) - return -EFAULT; - - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (qc.id && qc.id == s->qctrl[i].id) { - memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); - if (copy_to_user(arg, &qc, sizeof(qc))) - return -EFAULT; - return 0; - } - - return -EINVAL; -} - - -static int -sn9c102_vidioc_g_ctrl(struct sn9c102_device *cam, void __user *arg) -{ - struct sn9c102_sensor *s = &cam->sensor; - struct v4l2_control ctrl; - int err = 0; - u8 i; - - if (!s->get_ctrl && !s->set_ctrl) - return -EINVAL; - - if (copy_from_user(&ctrl, arg, sizeof(ctrl))) - return -EFAULT; - - if (!s->get_ctrl) { - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (ctrl.id && ctrl.id == s->qctrl[i].id) { - ctrl.value = s->_qctrl[i].default_value; - goto exit; - } - return -EINVAL; - } else - err = s->get_ctrl(cam, &ctrl); - -exit: - if (copy_to_user(arg, &ctrl, sizeof(ctrl))) - return -EFAULT; - - PDBGG("VIDIOC_G_CTRL: id %lu, value %lu", - (unsigned long)ctrl.id, (unsigned long)ctrl.value); - - return err; -} - - -static int -sn9c102_vidioc_s_ctrl(struct sn9c102_device *cam, void __user *arg) -{ - struct sn9c102_sensor *s = &cam->sensor; - struct v4l2_control ctrl; - u8 i; - int err = 0; - - if (!s->set_ctrl) - return -EINVAL; - - if (copy_from_user(&ctrl, arg, sizeof(ctrl))) - return -EFAULT; - - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) { - if (ctrl.id == s->qctrl[i].id) { - if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) - return -EINVAL; - if (ctrl.value < s->qctrl[i].minimum || - ctrl.value > s->qctrl[i].maximum) - return -ERANGE; - ctrl.value -= ctrl.value % s->qctrl[i].step; - break; - } - } - if (i == ARRAY_SIZE(s->qctrl)) - return -EINVAL; - err = s->set_ctrl(cam, &ctrl); - if (err) - return err; - - s->_qctrl[i].default_value = ctrl.value; - - PDBGG("VIDIOC_S_CTRL: id %lu, value %lu", - (unsigned long)ctrl.id, (unsigned long)ctrl.value); - - return 0; -} - - -static int -sn9c102_vidioc_cropcap(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_cropcap *cc = &(cam->sensor.cropcap); - - cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cc->pixelaspect.numerator = 1; - cc->pixelaspect.denominator = 1; - - if (copy_to_user(arg, cc, sizeof(*cc))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_g_crop(struct sn9c102_device *cam, void __user *arg) -{ - struct sn9c102_sensor *s = &cam->sensor; - struct v4l2_crop crop = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - }; - - memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); - - if (copy_to_user(arg, &crop, sizeof(crop))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_crop(struct sn9c102_device *cam, void __user *arg) -{ - struct sn9c102_sensor *s = &cam->sensor; - struct v4l2_crop crop; - struct v4l2_rect *rect; - struct v4l2_rect *bounds = &(s->cropcap.bounds); - struct v4l2_pix_format *pix_format = &(s->pix_format); - u8 scale; - const enum sn9c102_stream_state stream = cam->stream; - const u32 nbuffers = cam->nbuffers; - u32 i; - int err = 0; - - if (copy_from_user(&crop, arg, sizeof(crop))) - return -EFAULT; - - rect = &(crop.c); - - if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (cam->module_param.force_munmap) - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_S_CROP failed. " - "Unmap the buffers first."); - return -EBUSY; - } - - /* Preserve R,G or B origin */ - rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L; - rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L; - - if (rect->width < 16) - rect->width = 16; - if (rect->height < 16) - rect->height = 16; - if (rect->width > bounds->width) - rect->width = bounds->width; - if (rect->height > bounds->height) - rect->height = bounds->height; - if (rect->left < bounds->left) - rect->left = bounds->left; - if (rect->top < bounds->top) - rect->top = bounds->top; - if (rect->left + rect->width > bounds->left + bounds->width) - rect->left = bounds->left+bounds->width - rect->width; - if (rect->top + rect->height > bounds->top + bounds->height) - rect->top = bounds->top+bounds->height - rect->height; - - rect->width &= ~15L; - rect->height &= ~15L; - - if (SN9C102_PRESERVE_IMGSCALE) { - /* Calculate the actual scaling factor */ - u32 a, b; - a = rect->width * rect->height; - b = pix_format->width * pix_format->height; - scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; - } else - scale = 1; - - if (cam->stream == STREAM_ON) { - err = sn9c102_stream_interrupt(cam); - if (err) - return err; - } - - if (copy_to_user(arg, &crop, sizeof(crop))) { - cam->stream = stream; - return -EFAULT; - } - - if (cam->module_param.force_munmap || cam->io == IO_READ) - sn9c102_release_buffers(cam); - - err = sn9c102_set_crop(cam, rect); - if (s->set_crop) - err += s->set_crop(cam, rect); - err += sn9c102_set_scale(cam, scale); - - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " - "use the camera, close and open %s again.", - video_device_node_name(cam->v4ldev)); - return -EIO; - } - - s->pix_format.width = rect->width/scale; - s->pix_format.height = rect->height/scale; - memcpy(&(s->_rect), rect, sizeof(*rect)); - - if ((cam->module_param.force_munmap || cam->io == IO_READ) && - nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " - "use the camera, close and open %s again.", - video_device_node_name(cam->v4ldev)); - return -ENOMEM; - } - - if (cam->io == IO_READ) - sn9c102_empty_framequeues(cam); - else if (cam->module_param.force_munmap) - sn9c102_requeue_outqueue(cam); - - cam->stream = stream; - - return 0; -} - - -static int -sn9c102_vidioc_enum_framesizes(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_frmsizeenum frmsize; - - if (copy_from_user(&frmsize, arg, sizeof(frmsize))) - return -EFAULT; - - if (frmsize.index != 0) - return -EINVAL; - - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X && - frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8) - return -EINVAL; - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG && - frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8) - return -EINVAL; - break; - } - - frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE; - frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16; - frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16; - frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width; - frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height; - memset(&frmsize.reserved, 0, sizeof(frmsize.reserved)); - - if (copy_to_user(arg, &frmsize, sizeof(frmsize))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_enum_fmt(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_fmtdesc fmtd; - - if (copy_from_user(&fmtd, arg, sizeof(fmtd))) - return -EFAULT; - - if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (fmtd.index == 0) { - strcpy(fmtd.description, "bayer rgb"); - fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; - } else if (fmtd.index == 1) { - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - strcpy(fmtd.description, "compressed"); - fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - strcpy(fmtd.description, "JPEG"); - fmtd.pixelformat = V4L2_PIX_FMT_JPEG; - break; - } - fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; - } else - return -EINVAL; - - fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); - - if (copy_to_user(arg, &fmtd, sizeof(fmtd))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_g_fmt(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_format format; - struct v4l2_pix_format *pfmt = &(cam->sensor.pix_format); - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; - - if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ? - V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB; - pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X || - pfmt->pixelformat == V4L2_PIX_FMT_JPEG) - ? 0 : (pfmt->width * pfmt->priv) / 8; - pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); - pfmt->field = V4L2_FIELD_NONE; - memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); - - if (copy_to_user(arg, &format, sizeof(format))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_try_s_fmt(struct sn9c102_device *cam, unsigned int cmd, - void __user *arg) -{ - struct sn9c102_sensor *s = &cam->sensor; - struct v4l2_format format; - struct v4l2_pix_format *pix; - struct v4l2_pix_format *pfmt = &(s->pix_format); - struct v4l2_rect *bounds = &(s->cropcap.bounds); - struct v4l2_rect rect; - u8 scale; - const enum sn9c102_stream_state stream = cam->stream; - const u32 nbuffers = cam->nbuffers; - u32 i; - int err = 0; - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; - - pix = &(format.fmt.pix); - - if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - memcpy(&rect, &(s->_rect), sizeof(rect)); - - { /* calculate the actual scaling factor */ - u32 a, b; - a = rect.width * rect.height; - b = pix->width * pix->height; - scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; - } - - rect.width = scale * pix->width; - rect.height = scale * pix->height; - - if (rect.width < 16) - rect.width = 16; - if (rect.height < 16) - rect.height = 16; - if (rect.width > bounds->left + bounds->width - rect.left) - rect.width = bounds->left + bounds->width - rect.left; - if (rect.height > bounds->top + bounds->height - rect.top) - rect.height = bounds->top + bounds->height - rect.top; - - rect.width &= ~15L; - rect.height &= ~15L; - - { /* adjust the scaling factor */ - u32 a, b; - a = rect.width * rect.height; - b = pix->width * pix->height; - scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; - } - - pix->width = rect.width / scale; - pix->height = rect.height / scale; - - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && - pix->pixelformat != V4L2_PIX_FMT_SBGGR8) - pix->pixelformat = pfmt->pixelformat; - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - if (pix->pixelformat != V4L2_PIX_FMT_JPEG && - pix->pixelformat != V4L2_PIX_FMT_SBGGR8) - pix->pixelformat = pfmt->pixelformat; - break; - } - pix->priv = pfmt->priv; /* bpp */ - pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ? - V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB; - pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X || - pix->pixelformat == V4L2_PIX_FMT_JPEG) - ? 0 : (pix->width * pix->priv) / 8; - pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); - pix->field = V4L2_FIELD_NONE; - - if (cmd == VIDIOC_TRY_FMT) { - if (copy_to_user(arg, &format, sizeof(format))) - return -EFAULT; - return 0; - } - - if (cam->module_param.force_munmap) - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_S_FMT failed. Unmap the " - "buffers first."); - return -EBUSY; - } - - if (cam->stream == STREAM_ON) { - err = sn9c102_stream_interrupt(cam); - if (err) - return err; - } - - if (copy_to_user(arg, &format, sizeof(format))) { - cam->stream = stream; - return -EFAULT; - } - - if (cam->module_param.force_munmap || cam->io == IO_READ) - sn9c102_release_buffers(cam); - - err += sn9c102_set_pix_format(cam, pix); - err += sn9c102_set_crop(cam, &rect); - if (s->set_pix_format) - err += s->set_pix_format(cam, pix); - if (s->set_crop) - err += s->set_crop(cam, &rect); - err += sn9c102_set_scale(cam, scale); - - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " - "use the camera, close and open %s again.", - video_device_node_name(cam->v4ldev)); - return -EIO; - } - - memcpy(pfmt, pix, sizeof(*pix)); - memcpy(&(s->_rect), &rect, sizeof(rect)); - - if ((cam->module_param.force_munmap || cam->io == IO_READ) && - nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " - "use the camera, close and open %s again.", - video_device_node_name(cam->v4ldev)); - return -ENOMEM; - } - - if (cam->io == IO_READ) - sn9c102_empty_framequeues(cam); - else if (cam->module_param.force_munmap) - sn9c102_requeue_outqueue(cam); - - cam->stream = stream; - - return 0; -} - - -static int -sn9c102_vidioc_g_jpegcomp(struct sn9c102_device *cam, void __user *arg) -{ - if (copy_to_user(arg, &cam->compression, sizeof(cam->compression))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_jpegcomp(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_jpegcompression jc; - const enum sn9c102_stream_state stream = cam->stream; - int err = 0; - - if (copy_from_user(&jc, arg, sizeof(jc))) - return -EFAULT; - - if (jc.quality != 0 && jc.quality != 1) - return -EINVAL; - - if (cam->stream == STREAM_ON) { - err = sn9c102_stream_interrupt(cam); - if (err) - return err; - } - - err += sn9c102_set_compression(cam, &jc); - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware problems. " - "To use the camera, close and open %s again.", - video_device_node_name(cam->v4ldev)); - return -EIO; - } - - cam->compression.quality = jc.quality; - - cam->stream = stream; - - return 0; -} - - -static int -sn9c102_vidioc_reqbufs(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_requestbuffers rb; - u32 i; - int err; - - if (copy_from_user(&rb, arg, sizeof(rb))) - return -EFAULT; - - if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - rb.memory != V4L2_MEMORY_MMAP) - return -EINVAL; - - if (cam->io == IO_READ) { - DBG(3, "Close and open the device again to choose the mmap " - "I/O method"); - return -EBUSY; - } - - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are " - "still mapped."); - return -EBUSY; - } - - if (cam->stream == STREAM_ON) { - err = sn9c102_stream_interrupt(cam); - if (err) - return err; - } - - sn9c102_empty_framequeues(cam); - - sn9c102_release_buffers(cam); - if (rb.count) - rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP); - - if (copy_to_user(arg, &rb, sizeof(rb))) { - sn9c102_release_buffers(cam); - cam->io = IO_NONE; - return -EFAULT; - } - - cam->io = rb.count ? IO_MMAP : IO_NONE; - - return 0; -} - - -static int -sn9c102_vidioc_querybuf(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_buffer b; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b.index >= cam->nbuffers || cam->io != IO_MMAP) - return -EINVAL; - - b = cam->frame[b.index].buf; - - if (cam->frame[b.index].vma_use_count) - b.flags |= V4L2_BUF_FLAG_MAPPED; - - if (cam->frame[b.index].state == F_DONE) - b.flags |= V4L2_BUF_FLAG_DONE; - else if (cam->frame[b.index].state != F_UNUSED) - b.flags |= V4L2_BUF_FLAG_QUEUED; - - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_qbuf(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_buffer b; - unsigned long lock_flags; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b.index >= cam->nbuffers || cam->io != IO_MMAP) - return -EINVAL; - - if (cam->frame[b.index].state != F_UNUSED) - return -EINVAL; - - cam->frame[b.index].state = F_QUEUED; - - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - PDBGG("Frame #%lu queued", (unsigned long)b.index); - - return 0; -} - - -static int -sn9c102_vidioc_dqbuf(struct sn9c102_device *cam, struct file *filp, - void __user *arg) -{ - struct v4l2_buffer b; - struct sn9c102_frame_t *f; - unsigned long lock_flags; - long timeout; - int err = 0; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; - - if (list_empty(&cam->outqueue)) { - if (cam->stream == STREAM_OFF) - return -EINVAL; - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - if (!cam->module_param.frame_timeout) { - err = wait_event_interruptible - (cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED)); - if (err) - return err; - } else { - timeout = wait_event_interruptible_timeout - (cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - cam->module_param.frame_timeout * - 1000 * msecs_to_jiffies(1)); - if (timeout < 0) - return timeout; - else if (timeout == 0 && - !(cam->state & DEV_DISCONNECTED)) { - DBG(1, "Video frame timeout elapsed"); - return -EIO; - } - } - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - if (cam->state & DEV_MISCONFIGURED) - return -EIO; - } - - spin_lock_irqsave(&cam->queue_lock, lock_flags); - f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame); - list_del(cam->outqueue.next); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - f->state = F_UNUSED; - - b = f->buf; - if (f->vma_use_count) - b.flags |= V4L2_BUF_FLAG_MAPPED; - - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; - - PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index); - - return 0; -} - - -static int -sn9c102_vidioc_streamon(struct sn9c102_device *cam, void __user *arg) -{ - int type; - - if (copy_from_user(&type, arg, sizeof(type))) - return -EFAULT; - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; - - cam->stream = STREAM_ON; - - DBG(3, "Stream on"); - - return 0; -} - - -static int -sn9c102_vidioc_streamoff(struct sn9c102_device *cam, void __user *arg) -{ - int type, err; - - if (copy_from_user(&type, arg, sizeof(type))) - return -EFAULT; - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; - - if (cam->stream == STREAM_ON) { - err = sn9c102_stream_interrupt(cam); - if (err) - return err; - } - - sn9c102_empty_framequeues(cam); - - DBG(3, "Stream off"); - - return 0; -} - - -static int -sn9c102_vidioc_g_parm(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_streamparm sp; - - if (copy_from_user(&sp, arg, sizeof(sp))) - return -EFAULT; - - if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - sp.parm.capture.extendedmode = 0; - sp.parm.capture.readbuffers = cam->nreadbuffers; - - if (copy_to_user(arg, &sp, sizeof(sp))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_parm(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_streamparm sp; - - if (copy_from_user(&sp, arg, sizeof(sp))) - return -EFAULT; - - if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - sp.parm.capture.extendedmode = 0; - - if (sp.parm.capture.readbuffers == 0) - sp.parm.capture.readbuffers = cam->nreadbuffers; - - if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES) - sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES; - - if (copy_to_user(arg, &sp, sizeof(sp))) - return -EFAULT; - - cam->nreadbuffers = sp.parm.capture.readbuffers; - - return 0; -} - - -static int -sn9c102_vidioc_enumaudio(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_audio audio; - - if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) - return -EINVAL; - - if (copy_from_user(&audio, arg, sizeof(audio))) - return -EFAULT; - - if (audio.index != 0) - return -EINVAL; - - strcpy(audio.name, "Microphone"); - audio.capability = 0; - audio.mode = 0; - - if (copy_to_user(arg, &audio, sizeof(audio))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_g_audio(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_audio audio; - - if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) - return -EINVAL; - - if (copy_from_user(&audio, arg, sizeof(audio))) - return -EFAULT; - - memset(&audio, 0, sizeof(audio)); - strcpy(audio.name, "Microphone"); - - if (copy_to_user(arg, &audio, sizeof(audio))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_audio(struct sn9c102_device *cam, void __user *arg) -{ - struct v4l2_audio audio; - - if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) - return -EINVAL; - - if (copy_from_user(&audio, arg, sizeof(audio))) - return -EFAULT; - - if (audio.index != 0) - return -EINVAL; - - return 0; -} - - -static long sn9c102_ioctl_v4l2(struct file *filp, - unsigned int cmd, void __user *arg) -{ - struct sn9c102_device *cam = video_drvdata(filp); - - switch (cmd) { - - case VIDIOC_QUERYCAP: - return sn9c102_vidioc_querycap(cam, arg); - - case VIDIOC_ENUMINPUT: - return sn9c102_vidioc_enuminput(cam, arg); - - case VIDIOC_G_INPUT: - return sn9c102_vidioc_g_input(cam, arg); - - case VIDIOC_S_INPUT: - return sn9c102_vidioc_s_input(cam, arg); - - case VIDIOC_QUERYCTRL: - return sn9c102_vidioc_query_ctrl(cam, arg); - - case VIDIOC_G_CTRL: - return sn9c102_vidioc_g_ctrl(cam, arg); - - case VIDIOC_S_CTRL: - return sn9c102_vidioc_s_ctrl(cam, arg); - - case VIDIOC_CROPCAP: - return sn9c102_vidioc_cropcap(cam, arg); - - case VIDIOC_G_CROP: - return sn9c102_vidioc_g_crop(cam, arg); - - case VIDIOC_S_CROP: - return sn9c102_vidioc_s_crop(cam, arg); - - case VIDIOC_ENUM_FRAMESIZES: - return sn9c102_vidioc_enum_framesizes(cam, arg); - - case VIDIOC_ENUM_FMT: - return sn9c102_vidioc_enum_fmt(cam, arg); - - case VIDIOC_G_FMT: - return sn9c102_vidioc_g_fmt(cam, arg); - - case VIDIOC_TRY_FMT: - case VIDIOC_S_FMT: - return sn9c102_vidioc_try_s_fmt(cam, cmd, arg); - - case VIDIOC_G_JPEGCOMP: - return sn9c102_vidioc_g_jpegcomp(cam, arg); - - case VIDIOC_S_JPEGCOMP: - return sn9c102_vidioc_s_jpegcomp(cam, arg); - - case VIDIOC_REQBUFS: - return sn9c102_vidioc_reqbufs(cam, arg); - - case VIDIOC_QUERYBUF: - return sn9c102_vidioc_querybuf(cam, arg); - - case VIDIOC_QBUF: - return sn9c102_vidioc_qbuf(cam, arg); - - case VIDIOC_DQBUF: - return sn9c102_vidioc_dqbuf(cam, filp, arg); - - case VIDIOC_STREAMON: - return sn9c102_vidioc_streamon(cam, arg); - - case VIDIOC_STREAMOFF: - return sn9c102_vidioc_streamoff(cam, arg); - - case VIDIOC_G_PARM: - return sn9c102_vidioc_g_parm(cam, arg); - - case VIDIOC_S_PARM: - return sn9c102_vidioc_s_parm(cam, arg); - - case VIDIOC_ENUMAUDIO: - return sn9c102_vidioc_enumaudio(cam, arg); - - case VIDIOC_G_AUDIO: - return sn9c102_vidioc_g_audio(cam, arg); - - case VIDIOC_S_AUDIO: - return sn9c102_vidioc_s_audio(cam, arg); - - default: - return -ENOTTY; - - } -} - - -static long sn9c102_ioctl(struct file *filp, - unsigned int cmd, unsigned long arg) -{ - struct sn9c102_device *cam = video_drvdata(filp); - int err = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - V4LDBG(3, "sn9c102", cmd); - - err = sn9c102_ioctl_v4l2(filp, cmd, (void __user *)arg); - - mutex_unlock(&cam->fileop_mutex); - - return err; -} - -/*****************************************************************************/ - -static const struct v4l2_file_operations sn9c102_fops = { - .owner = THIS_MODULE, - .open = sn9c102_open, - .release = sn9c102_release, - .unlocked_ioctl = sn9c102_ioctl, - .read = sn9c102_read, - .poll = sn9c102_poll, - .mmap = sn9c102_mmap, -}; - -/*****************************************************************************/ - -/* It exists a single interface only. We do not need to validate anything. */ -static int -sn9c102_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct sn9c102_device *cam; - static unsigned int dev_nr; - unsigned int i; - int err = 0, r; - - cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL); - if (!cam) - return -ENOMEM; - - cam->usbdev = udev; - - /* register v4l2_device early so it can be used for printks */ - if (v4l2_device_register(&intf->dev, &cam->v4l2_dev)) { - dev_err(&intf->dev, "v4l2_device_register failed\n"); - err = -ENOMEM; - goto fail; - } - - cam->control_buffer = kzalloc(8, GFP_KERNEL); - if (!cam->control_buffer) { - DBG(1, "kzalloc() failed"); - err = -ENOMEM; - goto fail; - } - - cam->v4ldev = video_device_alloc(); - if (!cam->v4ldev) { - DBG(1, "video_device_alloc() failed"); - err = -ENOMEM; - goto fail; - } - - r = sn9c102_read_reg(cam, 0x00); - if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) { - DBG(1, "Sorry, this is not a SN9C1xx-based camera " - "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); - err = -ENODEV; - goto fail; - } - - cam->bridge = id->driver_info; - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - DBG(2, "SN9C10[12] PC Camera Controller detected " - "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); - break; - case BRIDGE_SN9C103: - DBG(2, "SN9C103 PC Camera Controller detected " - "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); - break; - case BRIDGE_SN9C105: - DBG(2, "SN9C105 PC Camera Controller detected " - "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); - break; - case BRIDGE_SN9C120: - DBG(2, "SN9C120 PC Camera Controller detected " - "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); - break; - } - - for (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) { - err = sn9c102_sensor_table[i](cam); - if (!err) - break; - } - - if (!err) { - DBG(2, "%s image sensor detected", cam->sensor.name); - DBG(3, "Support for %s maintained by %s", - cam->sensor.name, cam->sensor.maintainer); - } else { - DBG(1, "No supported image sensor detected for this bridge"); - err = -ENODEV; - goto fail; - } - - if (!(cam->bridge & cam->sensor.supported_bridge)) { - DBG(1, "Bridge not supported"); - err = -ENODEV; - goto fail; - } - - if (sn9c102_init(cam)) { - DBG(1, "Initialization failed. I will retry on open()."); - cam->state |= DEV_MISCONFIGURED; - } - - strcpy(cam->v4ldev->name, "SN9C1xx PC Camera"); - cam->v4ldev->fops = &sn9c102_fops; - cam->v4ldev->release = video_device_release; - cam->v4ldev->v4l2_dev = &cam->v4l2_dev; - - init_completion(&cam->probe); - - err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, - video_nr[dev_nr]); - if (err) { - DBG(1, "V4L2 device registration failed"); - if (err == -ENFILE && video_nr[dev_nr] == -1) - DBG(1, "Free /dev/videoX node not found"); - video_nr[dev_nr] = -1; - dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; - complete_all(&cam->probe); - goto fail; - } - - DBG(2, "V4L2 device registered as %s", - video_device_node_name(cam->v4ldev)); - - video_set_drvdata(cam->v4ldev, cam); - cam->module_param.force_munmap = force_munmap[dev_nr]; - cam->module_param.frame_timeout = frame_timeout[dev_nr]; - - dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; - -#ifdef CONFIG_VIDEO_ADV_DEBUG - err = sn9c102_create_sysfs(cam); - if (!err) - DBG(2, "Optional device control through 'sysfs' " - "interface ready"); - else - DBG(2, "Failed to create optional 'sysfs' interface for " - "device controlling. Error #%d", err); -#else - DBG(2, "Optional device control through 'sysfs' interface disabled"); - DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' " - "configuration option to enable it."); -#endif - - usb_set_intfdata(intf, cam); - kref_init(&cam->kref); - usb_get_dev(cam->usbdev); - - complete_all(&cam->probe); - - return 0; - -fail: - if (cam) { - kfree(cam->control_buffer); - if (cam->v4ldev) - video_device_release(cam->v4ldev); - v4l2_device_unregister(&cam->v4l2_dev); - kfree(cam); - } - return err; -} - - -static void sn9c102_usb_disconnect(struct usb_interface *intf) -{ - struct sn9c102_device *cam; - - down_write(&sn9c102_dev_lock); - - cam = usb_get_intfdata(intf); - - DBG(2, "Disconnecting %s...", cam->v4ldev->name); - - if (cam->users) { - DBG(2, "Device %s is open! Deregistration and memory " - "deallocation are deferred.", - video_device_node_name(cam->v4ldev)); - cam->state |= DEV_MISCONFIGURED; - sn9c102_stop_transfer(cam); - cam->state |= DEV_DISCONNECTED; - wake_up_interruptible(&cam->wait_frame); - wake_up(&cam->wait_stream); - } else - cam->state |= DEV_DISCONNECTED; - - wake_up_interruptible_all(&cam->wait_open); - - v4l2_device_disconnect(&cam->v4l2_dev); - - kref_put(&cam->kref, sn9c102_release_resources); - - up_write(&sn9c102_dev_lock); -} - - -static struct usb_driver sn9c102_usb_driver = { - .name = "sn9c102", - .id_table = sn9c102_id_table, - .probe = sn9c102_usb_probe, - .disconnect = sn9c102_usb_disconnect, -}; - -module_usb_driver(sn9c102_usb_driver); diff --git a/drivers/staging/media/sn9c102/sn9c102_devtable.h b/drivers/staging/media/sn9c102/sn9c102_devtable.h deleted file mode 100644 index b187a8a304eb..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_devtable.h +++ /dev/null @@ -1,145 +0,0 @@ -/*************************************************************************** - * Table of device identifiers of the SN9C1xx PC Camera Controllers * - * * - * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#ifndef _SN9C102_DEVTABLE_H_ -#define _SN9C102_DEVTABLE_H_ - -#include <linux/usb.h> - -struct sn9c102_device; - -/* - Each SN9C1xx camera has proper PID/VID identifiers. - SN9C103, SN9C105, SN9C120 support multiple interfaces, but we only have to - handle the video class interface. -*/ -#define SN9C102_USB_DEVICE(vend, prod, bridge) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ - USB_DEVICE_ID_MATCH_INT_CLASS, \ - .idVendor = (vend), \ - .idProduct = (prod), \ - .bInterfaceClass = 0xff, \ - .driver_info = (bridge) - -static const struct usb_device_id sn9c102_id_table[] = { - /* SN9C101 and SN9C102 */ -#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE - { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ - { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, -#endif - { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, /* not in sonixb */ -#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE - { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */ - { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), }, -#endif - { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, /* not in sonixb */ - /* SN9C103 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, non existent ? */ - { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, /* not in sonixb */ -#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE -/* { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, HY7131D/E */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, non existent ? */ - { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */ - { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, PAS106 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, TAS5130 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5110, non existent */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, non existent ? */ - { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, non existent ? */ -#endif - /* SN9C105 */ -#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE - { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), }, - { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), }, - { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, - { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), }, PO1030 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, OM6801 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, HV7131GP */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, MO4000 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), }, ICM105C */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, OV7648 */ - { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), }, - /* SN9C120 */ - { SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), }, po2030 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, om6801 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, S5K53BEB */ - { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */ - { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, - { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, - { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, - { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), }, -#endif - { } -}; - -/* - Probing functions: on success, you must attach the sensor to the camera - by calling sn9c102_attach_sensor(). - To enable the I2C communication, you might need to perform a really basic - initialization of the SN9C1XX chip. - Functions must return 0 on success, the appropriate error otherwise. -*/ -extern int sn9c102_probe_hv7131d(struct sn9c102_device *cam); -extern int sn9c102_probe_hv7131r(struct sn9c102_device *cam); -extern int sn9c102_probe_mi0343(struct sn9c102_device *cam); -extern int sn9c102_probe_mi0360(struct sn9c102_device *cam); -extern int sn9c102_probe_mt9v111(struct sn9c102_device *cam); -extern int sn9c102_probe_ov7630(struct sn9c102_device *cam); -extern int sn9c102_probe_ov7660(struct sn9c102_device *cam); -extern int sn9c102_probe_pas106b(struct sn9c102_device *cam); -extern int sn9c102_probe_pas202bcb(struct sn9c102_device *cam); -extern int sn9c102_probe_tas5110c1b(struct sn9c102_device *cam); -extern int sn9c102_probe_tas5110d(struct sn9c102_device *cam); -extern int sn9c102_probe_tas5130d1b(struct sn9c102_device *cam); - -#endif /* _SN9C102_DEVTABLE_H_ */ diff --git a/drivers/staging/media/sn9c102/sn9c102_hv7131d.c b/drivers/staging/media/sn9c102/sn9c102_hv7131d.c deleted file mode 100644 index f1d94f0190c6..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_hv7131d.c +++ /dev/null @@ -1,269 +0,0 @@ -/*************************************************************************** - * Plug-in for HV7131D image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int hv7131d_init(struct sn9c102_device *cam) -{ - int err; - - err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, - {0x00, 0x14}, {0x60, 0x17}, - {0x0e, 0x18}, {0xf2, 0x19}); - - err += sn9c102_i2c_write(cam, 0x01, 0x04); - err += sn9c102_i2c_write(cam, 0x02, 0x00); - err += sn9c102_i2c_write(cam, 0x28, 0x00); - - return err; -} - - -static int hv7131d_get_ctrl(struct sn9c102_device *cam, - struct v4l2_control *ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - { - int r1 = sn9c102_i2c_read(cam, 0x26), - r2 = sn9c102_i2c_read(cam, 0x27); - if (r1 < 0 || r2 < 0) - return -EIO; - ctrl->value = (r1 << 8) | (r2 & 0xff); - } - return 0; - case V4L2_CID_RED_BALANCE: - ctrl->value = sn9c102_i2c_read(cam, 0x31); - if (ctrl->value < 0) - return -EIO; - ctrl->value = 0x3f - (ctrl->value & 0x3f); - return 0; - case V4L2_CID_BLUE_BALANCE: - ctrl->value = sn9c102_i2c_read(cam, 0x33); - if (ctrl->value < 0) - return -EIO; - ctrl->value = 0x3f - (ctrl->value & 0x3f); - return 0; - case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = sn9c102_i2c_read(cam, 0x32); - if (ctrl->value < 0) - return -EIO; - ctrl->value = 0x3f - (ctrl->value & 0x3f); - return 0; - case SN9C102_V4L2_CID_RESET_LEVEL: - ctrl->value = sn9c102_i2c_read(cam, 0x30); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x3f; - return 0; - case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE: - ctrl->value = sn9c102_i2c_read(cam, 0x34); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x07; - return 0; - default: - return -EINVAL; - } -} - - -static int hv7131d_set_ctrl(struct sn9c102_device *cam, - const struct v4l2_control *ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x26, ctrl->value >> 8); - err += sn9c102_i2c_write(cam, 0x27, ctrl->value & 0xff); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x31, 0x3f - ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x33, 0x3f - ctrl->value); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_write(cam, 0x32, 0x3f - ctrl->value); - break; - case SN9C102_V4L2_CID_RESET_LEVEL: - err += sn9c102_i2c_write(cam, 0x30, ctrl->value); - break; - case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE: - err += sn9c102_i2c_write(cam, 0x34, ctrl->value); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int hv7131d_set_crop(struct sn9c102_device *cam, - const struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int hv7131d_set_pix_format(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x42, 0x19); - else - err += sn9c102_write_reg(cam, 0xf2, 0x19); - - return err; -} - - -static const struct sn9c102_sensor hv7131d = { - .name = "HV7131D", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x11, - .init = &hv7131d_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x0250, - .maximum = 0xffff, - .step = 0x0001, - .default_value = 0x0250, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x1e, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_RESET_LEVEL, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "reset level", - .minimum = 0x19, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x30, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "pixel bias voltage", - .minimum = 0x00, - .maximum = 0x07, - .step = 0x01, - .default_value = 0x02, - .flags = 0, - }, - }, - .get_ctrl = &hv7131d_get_ctrl, - .set_ctrl = &hv7131d_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &hv7131d_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &hv7131d_set_pix_format -}; - - -int sn9c102_probe_hv7131d(struct sn9c102_device *cam) -{ - int r0 = 0, r1 = 0, err; - - err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, - {0x28, 0x17}); - - r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00); - r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01); - if (err || r0 < 0 || r1 < 0) - return -EIO; - - if ((r0 != 0x00 && r0 != 0x01) || r1 != 0x04) - return -ENODEV; - - sn9c102_attach_sensor(cam, &hv7131d); - - return 0; -} diff --git a/drivers/staging/media/sn9c102/sn9c102_hv7131r.c b/drivers/staging/media/sn9c102/sn9c102_hv7131r.c deleted file mode 100644 index 51b24e000e88..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_hv7131r.c +++ /dev/null @@ -1,369 +0,0 @@ -/*************************************************************************** - * Plug-in for HV7131R image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int hv7131r_init(struct sn9c102_device *cam) -{ - int err = 0; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C103: - err = sn9c102_write_const_regs(cam, {0x00, 0x03}, {0x1a, 0x04}, - {0x20, 0x05}, {0x20, 0x06}, - {0x03, 0x10}, {0x00, 0x14}, - {0x60, 0x17}, {0x0a, 0x18}, - {0xf0, 0x19}, {0x1d, 0x1a}, - {0x10, 0x1b}, {0x02, 0x1c}, - {0x03, 0x1d}, {0x0f, 0x1e}, - {0x0c, 0x1f}, {0x00, 0x20}, - {0x10, 0x21}, {0x20, 0x22}, - {0x30, 0x23}, {0x40, 0x24}, - {0x50, 0x25}, {0x60, 0x26}, - {0x70, 0x27}, {0x80, 0x28}, - {0x90, 0x29}, {0xa0, 0x2a}, - {0xb0, 0x2b}, {0xc0, 0x2c}, - {0xd0, 0x2d}, {0xe0, 0x2e}, - {0xf0, 0x2f}, {0xff, 0x30}); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02}, - {0x00, 0x03}, {0x1a, 0x04}, - {0x44, 0x05}, {0x3e, 0x06}, - {0x1a, 0x07}, {0x03, 0x10}, - {0x08, 0x14}, {0xa3, 0x17}, - {0x4b, 0x18}, {0x00, 0x19}, - {0x1d, 0x1a}, {0x10, 0x1b}, - {0x02, 0x1c}, {0x03, 0x1d}, - {0x0f, 0x1e}, {0x0c, 0x1f}, - {0x00, 0x20}, {0x29, 0x21}, - {0x40, 0x22}, {0x54, 0x23}, - {0x66, 0x24}, {0x76, 0x25}, - {0x85, 0x26}, {0x94, 0x27}, - {0xa1, 0x28}, {0xae, 0x29}, - {0xbb, 0x2a}, {0xc7, 0x2b}, - {0xd3, 0x2c}, {0xde, 0x2d}, - {0xea, 0x2e}, {0xf4, 0x2f}, - {0xff, 0x30}, {0x00, 0x3F}, - {0xC7, 0x40}, {0x01, 0x41}, - {0x44, 0x42}, {0x00, 0x43}, - {0x44, 0x44}, {0x00, 0x45}, - {0x44, 0x46}, {0x00, 0x47}, - {0xC7, 0x48}, {0x01, 0x49}, - {0xC7, 0x4A}, {0x01, 0x4B}, - {0xC7, 0x4C}, {0x01, 0x4D}, - {0x44, 0x4E}, {0x00, 0x4F}, - {0x44, 0x50}, {0x00, 0x51}, - {0x44, 0x52}, {0x00, 0x53}, - {0xC7, 0x54}, {0x01, 0x55}, - {0xC7, 0x56}, {0x01, 0x57}, - {0xC7, 0x58}, {0x01, 0x59}, - {0x44, 0x5A}, {0x00, 0x5B}, - {0x44, 0x5C}, {0x00, 0x5D}, - {0x44, 0x5E}, {0x00, 0x5F}, - {0xC7, 0x60}, {0x01, 0x61}, - {0xC7, 0x62}, {0x01, 0x63}, - {0xC7, 0x64}, {0x01, 0x65}, - {0x44, 0x66}, {0x00, 0x67}, - {0x44, 0x68}, {0x00, 0x69}, - {0x44, 0x6A}, {0x00, 0x6B}, - {0xC7, 0x6C}, {0x01, 0x6D}, - {0xC7, 0x6E}, {0x01, 0x6F}, - {0xC7, 0x70}, {0x01, 0x71}, - {0x44, 0x72}, {0x00, 0x73}, - {0x44, 0x74}, {0x00, 0x75}, - {0x44, 0x76}, {0x00, 0x77}, - {0xC7, 0x78}, {0x01, 0x79}, - {0xC7, 0x7A}, {0x01, 0x7B}, - {0xC7, 0x7C}, {0x01, 0x7D}, - {0x44, 0x7E}, {0x00, 0x7F}, - {0x14, 0x84}, {0x00, 0x85}, - {0x27, 0x86}, {0x00, 0x87}, - {0x07, 0x88}, {0x00, 0x89}, - {0xEC, 0x8A}, {0x0f, 0x8B}, - {0xD8, 0x8C}, {0x0f, 0x8D}, - {0x3D, 0x8E}, {0x00, 0x8F}, - {0x3D, 0x90}, {0x00, 0x91}, - {0xCD, 0x92}, {0x0f, 0x93}, - {0xf7, 0x94}, {0x0f, 0x95}, - {0x0C, 0x96}, {0x00, 0x97}, - {0x00, 0x98}, {0x66, 0x99}, - {0x05, 0x9A}, {0x00, 0x9B}, - {0x04, 0x9C}, {0x00, 0x9D}, - {0x08, 0x9E}, {0x00, 0x9F}, - {0x2D, 0xC0}, {0x2D, 0xC1}, - {0x3A, 0xC2}, {0x05, 0xC3}, - {0x04, 0xC4}, {0x3F, 0xC5}, - {0x00, 0xC6}, {0x00, 0xC7}, - {0x50, 0xC8}, {0x3C, 0xC9}, - {0x28, 0xCA}, {0xD8, 0xCB}, - {0x14, 0xCC}, {0xEC, 0xCD}, - {0x32, 0xCE}, {0xDD, 0xCF}, - {0x32, 0xD0}, {0xDD, 0xD1}, - {0x6A, 0xD2}, {0x50, 0xD3}, - {0x00, 0xD4}, {0x00, 0xD5}, - {0x00, 0xD6}); - break; - default: - break; - } - - err += sn9c102_i2c_write(cam, 0x20, 0x00); - err += sn9c102_i2c_write(cam, 0x21, 0xd6); - err += sn9c102_i2c_write(cam, 0x25, 0x06); - - return err; -} - - -static int hv7131r_get_ctrl(struct sn9c102_device *cam, - struct v4l2_control *ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_GAIN: - ctrl->value = sn9c102_i2c_read(cam, 0x30); - if (ctrl->value < 0) - return -EIO; - return 0; - case V4L2_CID_RED_BALANCE: - ctrl->value = sn9c102_i2c_read(cam, 0x31); - if (ctrl->value < 0) - return -EIO; - ctrl->value = ctrl->value & 0x3f; - return 0; - case V4L2_CID_BLUE_BALANCE: - ctrl->value = sn9c102_i2c_read(cam, 0x33); - if (ctrl->value < 0) - return -EIO; - ctrl->value = ctrl->value & 0x3f; - return 0; - case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = sn9c102_i2c_read(cam, 0x32); - if (ctrl->value < 0) - return -EIO; - ctrl->value = ctrl->value & 0x3f; - return 0; - case V4L2_CID_BLACK_LEVEL: - ctrl->value = sn9c102_i2c_read(cam, 0x01); - if (ctrl->value < 0) - return -EIO; - ctrl->value = (ctrl->value & 0x08) ? 1 : 0; - return 0; - default: - return -EINVAL; - } -} - - -static int hv7131r_set_ctrl(struct sn9c102_device *cam, - const struct v4l2_control *ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x30, ctrl->value); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x31, ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x33, ctrl->value); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_write(cam, 0x32, ctrl->value); - break; - case V4L2_CID_BLACK_LEVEL: - { - int r = sn9c102_i2c_read(cam, 0x01); - - if (r < 0) - return -EIO; - err += sn9c102_i2c_write(cam, 0x01, - (ctrl->value<<3) | (r&0xf7)); - } - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int hv7131r_set_crop(struct sn9c102_device *cam, - const struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int hv7131r_set_pix_format(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix) -{ - int err = 0; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C103: - if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { - err += sn9c102_write_reg(cam, 0xa0, 0x19); - err += sn9c102_i2c_write(cam, 0x01, 0x04); - } else { - err += sn9c102_write_reg(cam, 0x30, 0x19); - err += sn9c102_i2c_write(cam, 0x01, 0x04); - } - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { - err += sn9c102_write_reg(cam, 0xa5, 0x17); - err += sn9c102_i2c_write(cam, 0x01, 0x24); - } else { - err += sn9c102_write_reg(cam, 0xa3, 0x17); - err += sn9c102_i2c_write(cam, 0x01, 0x04); - } - break; - default: - break; - } - - return err; -} - - -static const struct sn9c102_sensor hv7131r = { - .name = "HV7131R", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120, - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x11, - .init = &hv7131r_init, - .qctrl = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0x40, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x08, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x1a, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x2f, - .flags = 0, - }, - { - .id = V4L2_CID_BLACK_LEVEL, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto black level compensation", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - }, - .get_ctrl = &hv7131r_get_ctrl, - .set_ctrl = &hv7131r_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &hv7131r_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &hv7131r_set_pix_format -}; - - -int sn9c102_probe_hv7131r(struct sn9c102_device *cam) -{ - int devid, err; - - err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x02}, - {0x34, 0x01}, {0x20, 0x17}, - {0x34, 0x01}, {0x46, 0x01}); - - devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00); - if (err || devid < 0) - return -EIO; - - if (devid != 0x02) - return -ENODEV; - - sn9c102_attach_sensor(cam, &hv7131r); - - return 0; -} diff --git a/drivers/staging/media/sn9c102/sn9c102_mi0343.c b/drivers/staging/media/sn9c102/sn9c102_mi0343.c deleted file mode 100644 index b20fdb6541d3..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_mi0343.c +++ /dev/null @@ -1,352 +0,0 @@ -/*************************************************************************** - * Plug-in for MI-0343 image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int mi0343_init(struct sn9c102_device *cam) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - - err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, - {0x0a, 0x14}, {0x40, 0x01}, - {0x20, 0x17}, {0x07, 0x18}, - {0xa0, 0x19}); - - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, - 0x00, 0x01, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, - 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03, - 0x01, 0xe1, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04, - 0x02, 0x81, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05, - 0x00, 0x17, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06, - 0x00, 0x11, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62, - 0x04, 0x9a, 0, 0); - - return err; -} - - -static int mi0343_get_ctrl(struct sn9c102_device *cam, - struct v4l2_control *ctrl) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - u8 data[2]; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2, - data) < 0) - return -EIO; - ctrl->value = data[0]; - return 0; - case V4L2_CID_GAIN: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2, - data) < 0) - return -EIO; - break; - case V4L2_CID_HFLIP: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, - data) < 0) - return -EIO; - ctrl->value = data[1] & 0x20 ? 1 : 0; - return 0; - case V4L2_CID_VFLIP: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, - data) < 0) - return -EIO; - ctrl->value = data[1] & 0x80 ? 1 : 0; - return 0; - case V4L2_CID_RED_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2, - data) < 0) - return -EIO; - break; - case V4L2_CID_BLUE_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2, - data) < 0) - return -EIO; - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2, - data) < 0) - return -EIO; - break; - default: - return -EINVAL; - } - - switch (ctrl->id) { - case V4L2_CID_GAIN: - case V4L2_CID_RED_BALANCE: - case V4L2_CID_BLUE_BALANCE: - case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = data[1] | (data[0] << 8); - if (ctrl->value >= 0x10 && ctrl->value <= 0x3f) - ctrl->value -= 0x10; - else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f) - ctrl->value -= 0x60; - else if (ctrl->value >= 0xe0 && ctrl->value <= 0xff) - ctrl->value -= 0xe0; - } - - return 0; -} - - -static int mi0343_set_ctrl(struct sn9c102_device *cam, - const struct v4l2_control *ctrl) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - u16 reg = 0; - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_GAIN: - case V4L2_CID_RED_BALANCE: - case V4L2_CID_BLUE_BALANCE: - case SN9C102_V4L2_CID_GREEN_BALANCE: - if (ctrl->value <= (0x3f-0x10)) - reg = 0x10 + ctrl->value; - else if (ctrl->value <= ((0x3f-0x10) + (0x7f-0x60))) - reg = 0x60 + (ctrl->value - (0x3f-0x10)); - else - reg = 0xe0 + (ctrl->value - (0x3f-0x10) - (0x7f-0x60)); - break; - } - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x09, ctrl->value, 0x00, - 0, 0); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x35, reg >> 8, reg & 0xff, - 0, 0); - break; - case V4L2_CID_HFLIP: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x20, ctrl->value ? 0x40:0x00, - ctrl->value ? 0x20:0x00, - 0, 0); - break; - case V4L2_CID_VFLIP: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x20, ctrl->value ? 0x80:0x00, - ctrl->value ? 0x80:0x00, - 0, 0); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x2d, reg >> 8, reg & 0xff, - 0, 0); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x2c, reg >> 8, reg & 0xff, - 0, 0); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x2b, reg >> 8, reg & 0xff, - 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x2e, reg >> 8, reg & 0xff, - 0, 0); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int mi0343_set_crop(struct sn9c102_device *cam, - const struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int mi0343_set_pix_format(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) { - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x0a, 0x00, 0x03, 0, 0); - err += sn9c102_write_reg(cam, 0x20, 0x19); - } else { - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x0a, 0x00, 0x05, 0, 0); - err += sn9c102_write_reg(cam, 0xa0, 0x19); - } - - return err; -} - - -static const struct sn9c102_sensor mi0343 = { - .name = "MI-0343", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x5d, - .init = &mi0343_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x06, - .flags = 0, - }, - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),/*0x6d*/ - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - .flags = 0, - }, - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0), - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0), - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = ((0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0)), - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - }, - .get_ctrl = &mi0343_get_ctrl, - .set_ctrl = &mi0343_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &mi0343_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &mi0343_set_pix_format -}; - - -int sn9c102_probe_mi0343(struct sn9c102_device *cam) -{ - u8 data[2]; - - if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, - {0x28, 0x17})) - return -EIO; - - if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00, - 2, data) < 0) - return -EIO; - - if (data[1] != 0x42 || data[0] != 0xe3) - return -ENODEV; - - sn9c102_attach_sensor(cam, &mi0343); - - return 0; -} diff --git a/drivers/staging/media/sn9c102/sn9c102_mi0360.c b/drivers/staging/media/sn9c102/sn9c102_mi0360.c deleted file mode 100644 index 5f21d1b43e32..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_mi0360.c +++ /dev/null @@ -1,453 +0,0 @@ -/*************************************************************************** - * Plug-in for MI-0360 image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int mi0360_init(struct sn9c102_device *cam) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C103: - err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, - {0x0a, 0x14}, {0x40, 0x01}, - {0x20, 0x17}, {0x07, 0x18}, - {0xa0, 0x19}, {0x02, 0x1c}, - {0x03, 0x1d}, {0x0f, 0x1e}, - {0x0c, 0x1f}, {0x00, 0x20}, - {0x10, 0x21}, {0x20, 0x22}, - {0x30, 0x23}, {0x40, 0x24}, - {0x50, 0x25}, {0x60, 0x26}, - {0x70, 0x27}, {0x80, 0x28}, - {0x90, 0x29}, {0xa0, 0x2a}, - {0xb0, 0x2b}, {0xc0, 0x2c}, - {0xd0, 0x2d}, {0xe0, 0x2e}, - {0xf0, 0x2f}, {0xff, 0x30}); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02}, - {0x00, 0x03}, {0x1a, 0x04}, - {0x50, 0x05}, {0x20, 0x06}, - {0x10, 0x07}, {0x03, 0x10}, - {0x08, 0x14}, {0xa2, 0x17}, - {0x47, 0x18}, {0x00, 0x19}, - {0x1d, 0x1a}, {0x10, 0x1b}, - {0x02, 0x1c}, {0x03, 0x1d}, - {0x0f, 0x1e}, {0x0c, 0x1f}, - {0x00, 0x20}, {0x29, 0x21}, - {0x40, 0x22}, {0x54, 0x23}, - {0x66, 0x24}, {0x76, 0x25}, - {0x85, 0x26}, {0x94, 0x27}, - {0xa1, 0x28}, {0xae, 0x29}, - {0xbb, 0x2a}, {0xc7, 0x2b}, - {0xd3, 0x2c}, {0xde, 0x2d}, - {0xea, 0x2e}, {0xf4, 0x2f}, - {0xff, 0x30}, {0x00, 0x3F}, - {0xC7, 0x40}, {0x01, 0x41}, - {0x44, 0x42}, {0x00, 0x43}, - {0x44, 0x44}, {0x00, 0x45}, - {0x44, 0x46}, {0x00, 0x47}, - {0xC7, 0x48}, {0x01, 0x49}, - {0xC7, 0x4A}, {0x01, 0x4B}, - {0xC7, 0x4C}, {0x01, 0x4D}, - {0x44, 0x4E}, {0x00, 0x4F}, - {0x44, 0x50}, {0x00, 0x51}, - {0x44, 0x52}, {0x00, 0x53}, - {0xC7, 0x54}, {0x01, 0x55}, - {0xC7, 0x56}, {0x01, 0x57}, - {0xC7, 0x58}, {0x01, 0x59}, - {0x44, 0x5A}, {0x00, 0x5B}, - {0x44, 0x5C}, {0x00, 0x5D}, - {0x44, 0x5E}, {0x00, 0x5F}, - {0xC7, 0x60}, {0x01, 0x61}, - {0xC7, 0x62}, {0x01, 0x63}, - {0xC7, 0x64}, {0x01, 0x65}, - {0x44, 0x66}, {0x00, 0x67}, - {0x44, 0x68}, {0x00, 0x69}, - {0x44, 0x6A}, {0x00, 0x6B}, - {0xC7, 0x6C}, {0x01, 0x6D}, - {0xC7, 0x6E}, {0x01, 0x6F}, - {0xC7, 0x70}, {0x01, 0x71}, - {0x44, 0x72}, {0x00, 0x73}, - {0x44, 0x74}, {0x00, 0x75}, - {0x44, 0x76}, {0x00, 0x77}, - {0xC7, 0x78}, {0x01, 0x79}, - {0xC7, 0x7A}, {0x01, 0x7B}, - {0xC7, 0x7C}, {0x01, 0x7D}, - {0x44, 0x7E}, {0x00, 0x7F}, - {0x14, 0x84}, {0x00, 0x85}, - {0x27, 0x86}, {0x00, 0x87}, - {0x07, 0x88}, {0x00, 0x89}, - {0xEC, 0x8A}, {0x0f, 0x8B}, - {0xD8, 0x8C}, {0x0f, 0x8D}, - {0x3D, 0x8E}, {0x00, 0x8F}, - {0x3D, 0x90}, {0x00, 0x91}, - {0xCD, 0x92}, {0x0f, 0x93}, - {0xf7, 0x94}, {0x0f, 0x95}, - {0x0C, 0x96}, {0x00, 0x97}, - {0x00, 0x98}, {0x66, 0x99}, - {0x05, 0x9A}, {0x00, 0x9B}, - {0x04, 0x9C}, {0x00, 0x9D}, - {0x08, 0x9E}, {0x00, 0x9F}, - {0x2D, 0xC0}, {0x2D, 0xC1}, - {0x3A, 0xC2}, {0x05, 0xC3}, - {0x04, 0xC4}, {0x3F, 0xC5}, - {0x00, 0xC6}, {0x00, 0xC7}, - {0x50, 0xC8}, {0x3C, 0xC9}, - {0x28, 0xCA}, {0xD8, 0xCB}, - {0x14, 0xCC}, {0xEC, 0xCD}, - {0x32, 0xCE}, {0xDD, 0xCF}, - {0x32, 0xD0}, {0xDD, 0xD1}, - {0x6A, 0xD2}, {0x50, 0xD3}, - {0x00, 0xD4}, {0x00, 0xD5}, - {0x00, 0xD6}); - break; - default: - break; - } - - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, - 0x00, 0x01, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, - 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03, - 0x01, 0xe1, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04, - 0x02, 0x81, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05, - 0x00, 0x17, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06, - 0x00, 0x11, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62, - 0x04, 0x9a, 0, 0); - - return err; -} - - -static int mi0360_get_ctrl(struct sn9c102_device *cam, - struct v4l2_control *ctrl) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - u8 data[2]; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2, - data) < 0) - return -EIO; - ctrl->value = data[0]; - return 0; - case V4L2_CID_GAIN: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2, - data) < 0) - return -EIO; - ctrl->value = data[1]; - return 0; - case V4L2_CID_RED_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2, - data) < 0) - return -EIO; - ctrl->value = data[1]; - return 0; - case V4L2_CID_BLUE_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2, - data) < 0) - return -EIO; - ctrl->value = data[1]; - return 0; - case SN9C102_V4L2_CID_GREEN_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2, - data) < 0) - return -EIO; - ctrl->value = data[1]; - return 0; - case V4L2_CID_HFLIP: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, - data) < 0) - return -EIO; - ctrl->value = data[1] & 0x20 ? 1 : 0; - return 0; - case V4L2_CID_VFLIP: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, - data) < 0) - return -EIO; - ctrl->value = data[1] & 0x80 ? 1 : 0; - return 0; - default: - return -EINVAL; - } - - return 0; -} - - -static int mi0360_set_ctrl(struct sn9c102_device *cam, - const struct v4l2_control *ctrl) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x09, ctrl->value, 0x00, - 0, 0); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x35, 0x03, ctrl->value, - 0, 0); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x2c, 0x03, ctrl->value, - 0, 0); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x2d, 0x03, ctrl->value, - 0, 0); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x2b, 0x03, ctrl->value, - 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x2e, 0x03, ctrl->value, - 0, 0); - break; - case V4L2_CID_HFLIP: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x20, ctrl->value ? 0x40:0x00, - ctrl->value ? 0x20:0x00, - 0, 0); - break; - case V4L2_CID_VFLIP: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x20, ctrl->value ? 0x80:0x00, - ctrl->value ? 0x80:0x00, - 0, 0); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int mi0360_set_crop(struct sn9c102_device *cam, - const struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C103: - h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0; - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1; - break; - default: - break; - } - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int mi0360_set_pix_format(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x0a, 0x00, 0x05, 0, 0); - err += sn9c102_write_reg(cam, 0x60, 0x19); - if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 || - sn9c102_get_bridge(cam) == BRIDGE_SN9C120) - err += sn9c102_write_reg(cam, 0xa6, 0x17); - } else { - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x0a, 0x00, 0x02, 0, 0); - err += sn9c102_write_reg(cam, 0x20, 0x19); - if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 || - sn9c102_get_bridge(cam) == BRIDGE_SN9C120) - err += sn9c102_write_reg(cam, 0xa2, 0x17); - } - - return err; -} - - -static const struct sn9c102_sensor mi0360 = { - .name = "MI-0360", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x5d, - .init = &mi0360_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x05, - .flags = 0, - }, - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x25, - .flags = 0, - }, - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - .flags = 0, - }, - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x0f, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x32, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x25, - .flags = 0, - }, - }, - .get_ctrl = &mi0360_get_ctrl, - .set_ctrl = &mi0360_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &mi0360_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &mi0360_set_pix_format -}; - - -int sn9c102_probe_mi0360(struct sn9c102_device *cam) -{ - - u8 data[2]; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C103: - if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, - {0x28, 0x17})) - return -EIO; - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - if (sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1}, - {0x01, 0x01}, {0x00, 0x01}, - {0x28, 0x17})) - return -EIO; - break; - default: - break; - } - - if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00, - 2, data) < 0) - return -EIO; - - if (data[0] != 0x82 || data[1] != 0x43) - return -ENODEV; - - sn9c102_attach_sensor(cam, &mi0360); - - return 0; -} diff --git a/drivers/staging/media/sn9c102/sn9c102_mt9v111.c b/drivers/staging/media/sn9c102/sn9c102_mt9v111.c deleted file mode 100644 index 95986eb492e4..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_mt9v111.c +++ /dev/null @@ -1,260 +0,0 @@ -/*************************************************************************** - * Plug-in for MT9V111 image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int mt9v111_init(struct sn9c102_device *cam) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - - err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02}, - {0x00, 0x03}, {0x1a, 0x04}, - {0x1f, 0x05}, {0x20, 0x06}, - {0x1f, 0x07}, {0x81, 0x08}, - {0x5c, 0x09}, {0x00, 0x0a}, - {0x00, 0x0b}, {0x00, 0x0c}, - {0x00, 0x0d}, {0x00, 0x0e}, - {0x00, 0x0f}, {0x03, 0x10}, - {0x00, 0x11}, {0x00, 0x12}, - {0x02, 0x13}, {0x14, 0x14}, - {0x28, 0x15}, {0x1e, 0x16}, - {0xe2, 0x17}, {0x06, 0x18}, - {0x00, 0x19}, {0x00, 0x1a}, - {0x00, 0x1b}, {0x08, 0x20}, - {0x39, 0x21}, {0x51, 0x22}, - {0x63, 0x23}, {0x73, 0x24}, - {0x82, 0x25}, {0x8f, 0x26}, - {0x9b, 0x27}, {0xa7, 0x28}, - {0xb1, 0x29}, {0xbc, 0x2a}, - {0xc6, 0x2b}, {0xcf, 0x2c}, - {0xd8, 0x2d}, {0xe1, 0x2e}, - {0xea, 0x2f}, {0xf2, 0x30}, - {0x13, 0x84}, {0x00, 0x85}, - {0x25, 0x86}, {0x00, 0x87}, - {0x07, 0x88}, {0x00, 0x89}, - {0xee, 0x8a}, {0x0f, 0x8b}, - {0xe5, 0x8c}, {0x0f, 0x8d}, - {0x2e, 0x8e}, {0x00, 0x8f}, - {0x30, 0x90}, {0x00, 0x91}, - {0xd4, 0x92}, {0x0f, 0x93}, - {0xfc, 0x94}, {0x0f, 0x95}, - {0x14, 0x96}, {0x00, 0x97}, - {0x00, 0x98}, {0x60, 0x99}, - {0x07, 0x9a}, {0x40, 0x9b}, - {0x20, 0x9c}, {0x00, 0x9d}, - {0x00, 0x9e}, {0x00, 0x9f}, - {0x2d, 0xc0}, {0x2d, 0xc1}, - {0x3a, 0xc2}, {0x05, 0xc3}, - {0x04, 0xc4}, {0x3f, 0xc5}, - {0x00, 0xc6}, {0x00, 0xc7}, - {0x50, 0xc8}, {0x3c, 0xc9}, - {0x28, 0xca}, {0xd8, 0xcb}, - {0x14, 0xcc}, {0xec, 0xcd}, - {0x32, 0xce}, {0xdd, 0xcf}, - {0x2d, 0xd0}, {0xdd, 0xd1}, - {0x6a, 0xd2}, {0x50, 0xd3}, - {0x60, 0xd4}, {0x00, 0xd5}, - {0x00, 0xd6}); - - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01, - 0x00, 0x01, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, - 0x00, 0x01, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, - 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08, - 0x04, 0x80, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01, - 0x00, 0x04, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08, - 0x00, 0x08, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x02, - 0x00, 0x16, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03, - 0x01, 0xe7, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04, - 0x02, 0x87, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06, - 0x00, 0x40, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05, - 0x00, 0x09, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x07, - 0x30, 0x02, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0c, - 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x12, - 0x00, 0xb0, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x13, - 0x00, 0x7c, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x1e, - 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20, - 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20, - 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01, - 0x00, 0x04, 0, 0); - - return err; -} - -static int mt9v111_get_ctrl(struct sn9c102_device *cam, - struct v4l2_control *ctrl) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - u8 data[2]; - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_VFLIP: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, - data) < 0) - return -EIO; - ctrl->value = data[1] & 0x80 ? 1 : 0; - return 0; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - -static int mt9v111_set_ctrl(struct sn9c102_device *cam, - const struct v4l2_control *ctrl) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_VFLIP: - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x20, - ctrl->value ? 0x80 : 0x00, - ctrl->value ? 0x80 : 0x00, 0, - 0); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - -static int mt9v111_set_crop(struct sn9c102_device *cam, - const struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - u8 v_start = (u8) (rect->top - s->cropcap.bounds.top) + 2; - - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - -static int mt9v111_set_pix_format(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { - err += sn9c102_write_reg(cam, 0xb4, 0x17); - } else { - err += sn9c102_write_reg(cam, 0xe2, 0x17); - } - - return err; -} - - -static const struct sn9c102_sensor mt9v111 = { - .name = "MT9V111", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x5c, - .init = &mt9v111_init, - .qctrl = { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - .flags = 0, - }, - }, - .get_ctrl = &mt9v111_get_ctrl, - .set_ctrl = &mt9v111_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &mt9v111_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &mt9v111_set_pix_format -}; - - -int sn9c102_probe_mt9v111(struct sn9c102_device *cam) -{ - u8 data[2]; - int err = 0; - - err += sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1}, - {0x29, 0x01}, {0x42, 0x17}, - {0x62, 0x17}, {0x08, 0x01}); - err += sn9c102_i2c_try_raw_write(cam, &mt9v111, 4, - mt9v111.i2c_slave_id, 0x01, 0x00, - 0x04, 0, 0); - if (err || sn9c102_i2c_try_raw_read(cam, &mt9v111, - mt9v111.i2c_slave_id, 0x36, 2, - data) < 0) - return -EIO; - - if (data[0] != 0x82 || data[1] != 0x3a) - return -ENODEV; - - sn9c102_attach_sensor(cam, &mt9v111); - - return 0; -} diff --git a/drivers/staging/media/sn9c102/sn9c102_ov7630.c b/drivers/staging/media/sn9c102/sn9c102_ov7630.c deleted file mode 100644 index 9ec304dc4705..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_ov7630.c +++ /dev/null @@ -1,634 +0,0 @@ -/*************************************************************************** - * Plug-in for OV7630 image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int ov7630_init(struct sn9c102_device *cam) -{ - int err = 0; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - err = sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, - {0x0f, 0x18}, {0x50, 0x19}); - - err += sn9c102_i2c_write(cam, 0x12, 0x8d); - err += sn9c102_i2c_write(cam, 0x12, 0x0d); - err += sn9c102_i2c_write(cam, 0x11, 0x00); - err += sn9c102_i2c_write(cam, 0x15, 0x35); - err += sn9c102_i2c_write(cam, 0x16, 0x03); - err += sn9c102_i2c_write(cam, 0x17, 0x1c); - err += sn9c102_i2c_write(cam, 0x18, 0xbd); - err += sn9c102_i2c_write(cam, 0x19, 0x06); - err += sn9c102_i2c_write(cam, 0x1a, 0xf6); - err += sn9c102_i2c_write(cam, 0x1b, 0x04); - err += sn9c102_i2c_write(cam, 0x20, 0x44); - err += sn9c102_i2c_write(cam, 0x23, 0xee); - err += sn9c102_i2c_write(cam, 0x26, 0xa0); - err += sn9c102_i2c_write(cam, 0x27, 0x9a); - err += sn9c102_i2c_write(cam, 0x28, 0x20); - err += sn9c102_i2c_write(cam, 0x29, 0x30); - err += sn9c102_i2c_write(cam, 0x2f, 0x3d); - err += sn9c102_i2c_write(cam, 0x30, 0x24); - err += sn9c102_i2c_write(cam, 0x32, 0x86); - err += sn9c102_i2c_write(cam, 0x60, 0xa9); - err += sn9c102_i2c_write(cam, 0x61, 0x42); - err += sn9c102_i2c_write(cam, 0x65, 0x00); - err += sn9c102_i2c_write(cam, 0x69, 0x38); - err += sn9c102_i2c_write(cam, 0x6f, 0x88); - err += sn9c102_i2c_write(cam, 0x70, 0x0b); - err += sn9c102_i2c_write(cam, 0x71, 0x00); - err += sn9c102_i2c_write(cam, 0x74, 0x21); - err += sn9c102_i2c_write(cam, 0x7d, 0xf7); - break; - case BRIDGE_SN9C103: - err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03}, - {0x1a, 0x04}, {0x20, 0x05}, - {0x20, 0x06}, {0x20, 0x07}, - {0x03, 0x10}, {0x0a, 0x14}, - {0x60, 0x17}, {0x0f, 0x18}, - {0x50, 0x19}, {0x1d, 0x1a}, - {0x10, 0x1b}, {0x02, 0x1c}, - {0x03, 0x1d}, {0x0f, 0x1e}, - {0x0c, 0x1f}, {0x00, 0x20}, - {0x10, 0x21}, {0x20, 0x22}, - {0x30, 0x23}, {0x40, 0x24}, - {0x50, 0x25}, {0x60, 0x26}, - {0x70, 0x27}, {0x80, 0x28}, - {0x90, 0x29}, {0xa0, 0x2a}, - {0xb0, 0x2b}, {0xc0, 0x2c}, - {0xd0, 0x2d}, {0xe0, 0x2e}, - {0xf0, 0x2f}, {0xff, 0x30}); - - err += sn9c102_i2c_write(cam, 0x12, 0x8d); - err += sn9c102_i2c_write(cam, 0x12, 0x0d); - err += sn9c102_i2c_write(cam, 0x15, 0x34); - err += sn9c102_i2c_write(cam, 0x11, 0x01); - err += sn9c102_i2c_write(cam, 0x1b, 0x04); - err += sn9c102_i2c_write(cam, 0x20, 0x44); - err += sn9c102_i2c_write(cam, 0x23, 0xee); - err += sn9c102_i2c_write(cam, 0x26, 0xa0); - err += sn9c102_i2c_write(cam, 0x27, 0x9a); - err += sn9c102_i2c_write(cam, 0x28, 0x20); - err += sn9c102_i2c_write(cam, 0x29, 0x30); - err += sn9c102_i2c_write(cam, 0x2f, 0x3d); - err += sn9c102_i2c_write(cam, 0x30, 0x24); - err += sn9c102_i2c_write(cam, 0x32, 0x86); - err += sn9c102_i2c_write(cam, 0x60, 0xa9); - err += sn9c102_i2c_write(cam, 0x61, 0x42); - err += sn9c102_i2c_write(cam, 0x65, 0x00); - err += sn9c102_i2c_write(cam, 0x69, 0x38); - err += sn9c102_i2c_write(cam, 0x6f, 0x88); - err += sn9c102_i2c_write(cam, 0x70, 0x0b); - err += sn9c102_i2c_write(cam, 0x71, 0x00); - err += sn9c102_i2c_write(cam, 0x74, 0x21); - err += sn9c102_i2c_write(cam, 0x7d, 0xf7); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03}, - {0x1a, 0x04}, {0x03, 0x10}, - {0x0a, 0x14}, {0xe2, 0x17}, - {0x0b, 0x18}, {0x00, 0x19}, - {0x1d, 0x1a}, {0x10, 0x1b}, - {0x02, 0x1c}, {0x03, 0x1d}, - {0x0f, 0x1e}, {0x0c, 0x1f}, - {0x00, 0x20}, {0x24, 0x21}, - {0x3b, 0x22}, {0x47, 0x23}, - {0x60, 0x24}, {0x71, 0x25}, - {0x80, 0x26}, {0x8f, 0x27}, - {0x9d, 0x28}, {0xaa, 0x29}, - {0xb8, 0x2a}, {0xc4, 0x2b}, - {0xd1, 0x2c}, {0xdd, 0x2d}, - {0xe8, 0x2e}, {0xf4, 0x2f}, - {0xff, 0x30}, {0x00, 0x3f}, - {0xc7, 0x40}, {0x01, 0x41}, - {0x44, 0x42}, {0x00, 0x43}, - {0x44, 0x44}, {0x00, 0x45}, - {0x44, 0x46}, {0x00, 0x47}, - {0xc7, 0x48}, {0x01, 0x49}, - {0xc7, 0x4a}, {0x01, 0x4b}, - {0xc7, 0x4c}, {0x01, 0x4d}, - {0x44, 0x4e}, {0x00, 0x4f}, - {0x44, 0x50}, {0x00, 0x51}, - {0x44, 0x52}, {0x00, 0x53}, - {0xc7, 0x54}, {0x01, 0x55}, - {0xc7, 0x56}, {0x01, 0x57}, - {0xc7, 0x58}, {0x01, 0x59}, - {0x44, 0x5a}, {0x00, 0x5b}, - {0x44, 0x5c}, {0x00, 0x5d}, - {0x44, 0x5e}, {0x00, 0x5f}, - {0xc7, 0x60}, {0x01, 0x61}, - {0xc7, 0x62}, {0x01, 0x63}, - {0xc7, 0x64}, {0x01, 0x65}, - {0x44, 0x66}, {0x00, 0x67}, - {0x44, 0x68}, {0x00, 0x69}, - {0x44, 0x6a}, {0x00, 0x6b}, - {0xc7, 0x6c}, {0x01, 0x6d}, - {0xc7, 0x6e}, {0x01, 0x6f}, - {0xc7, 0x70}, {0x01, 0x71}, - {0x44, 0x72}, {0x00, 0x73}, - {0x44, 0x74}, {0x00, 0x75}, - {0x44, 0x76}, {0x00, 0x77}, - {0xc7, 0x78}, {0x01, 0x79}, - {0xc7, 0x7a}, {0x01, 0x7b}, - {0xc7, 0x7c}, {0x01, 0x7d}, - {0x44, 0x7e}, {0x00, 0x7f}, - {0x17, 0x84}, {0x00, 0x85}, - {0x2e, 0x86}, {0x00, 0x87}, - {0x09, 0x88}, {0x00, 0x89}, - {0xe8, 0x8a}, {0x0f, 0x8b}, - {0xda, 0x8c}, {0x0f, 0x8d}, - {0x40, 0x8e}, {0x00, 0x8f}, - {0x37, 0x90}, {0x00, 0x91}, - {0xcf, 0x92}, {0x0f, 0x93}, - {0xfa, 0x94}, {0x0f, 0x95}, - {0x00, 0x96}, {0x00, 0x97}, - {0x00, 0x98}, {0x66, 0x99}, - {0x00, 0x9a}, {0x40, 0x9b}, - {0x20, 0x9c}, {0x00, 0x9d}, - {0x00, 0x9e}, {0x00, 0x9f}, - {0x2d, 0xc0}, {0x2d, 0xc1}, - {0x3a, 0xc2}, {0x00, 0xc3}, - {0x04, 0xc4}, {0x3f, 0xc5}, - {0x00, 0xc6}, {0x00, 0xc7}, - {0x50, 0xc8}, {0x3c, 0xc9}, - {0x28, 0xca}, {0xd8, 0xcb}, - {0x14, 0xcc}, {0xec, 0xcd}, - {0x32, 0xce}, {0xdd, 0xcf}, - {0x32, 0xd0}, {0xdd, 0xd1}, - {0x6a, 0xd2}, {0x50, 0xd3}, - {0x60, 0xd4}, {0x00, 0xd5}, - {0x00, 0xd6}); - - err += sn9c102_i2c_write(cam, 0x12, 0x80); - err += sn9c102_i2c_write(cam, 0x12, 0x48); - err += sn9c102_i2c_write(cam, 0x01, 0x80); - err += sn9c102_i2c_write(cam, 0x02, 0x80); - err += sn9c102_i2c_write(cam, 0x03, 0x80); - err += sn9c102_i2c_write(cam, 0x04, 0x10); - err += sn9c102_i2c_write(cam, 0x05, 0x20); - err += sn9c102_i2c_write(cam, 0x06, 0x80); - err += sn9c102_i2c_write(cam, 0x11, 0x00); - err += sn9c102_i2c_write(cam, 0x0c, 0x20); - err += sn9c102_i2c_write(cam, 0x0d, 0x20); - err += sn9c102_i2c_write(cam, 0x15, 0x80); - err += sn9c102_i2c_write(cam, 0x16, 0x03); - err += sn9c102_i2c_write(cam, 0x17, 0x1b); - err += sn9c102_i2c_write(cam, 0x18, 0xbd); - err += sn9c102_i2c_write(cam, 0x19, 0x05); - err += sn9c102_i2c_write(cam, 0x1a, 0xf6); - err += sn9c102_i2c_write(cam, 0x1b, 0x04); - err += sn9c102_i2c_write(cam, 0x21, 0x1b); - err += sn9c102_i2c_write(cam, 0x22, 0x00); - err += sn9c102_i2c_write(cam, 0x23, 0xde); - err += sn9c102_i2c_write(cam, 0x24, 0x10); - err += sn9c102_i2c_write(cam, 0x25, 0x8a); - err += sn9c102_i2c_write(cam, 0x26, 0xa0); - err += sn9c102_i2c_write(cam, 0x27, 0xca); - err += sn9c102_i2c_write(cam, 0x28, 0xa2); - err += sn9c102_i2c_write(cam, 0x29, 0x74); - err += sn9c102_i2c_write(cam, 0x2a, 0x88); - err += sn9c102_i2c_write(cam, 0x2b, 0x34); - err += sn9c102_i2c_write(cam, 0x2c, 0x88); - err += sn9c102_i2c_write(cam, 0x2e, 0x00); - err += sn9c102_i2c_write(cam, 0x2f, 0x00); - err += sn9c102_i2c_write(cam, 0x30, 0x00); - err += sn9c102_i2c_write(cam, 0x32, 0xc2); - err += sn9c102_i2c_write(cam, 0x33, 0x08); - err += sn9c102_i2c_write(cam, 0x4c, 0x40); - err += sn9c102_i2c_write(cam, 0x4d, 0xf3); - err += sn9c102_i2c_write(cam, 0x60, 0x05); - err += sn9c102_i2c_write(cam, 0x61, 0x40); - err += sn9c102_i2c_write(cam, 0x62, 0x12); - err += sn9c102_i2c_write(cam, 0x63, 0x57); - err += sn9c102_i2c_write(cam, 0x64, 0x73); - err += sn9c102_i2c_write(cam, 0x65, 0x00); - err += sn9c102_i2c_write(cam, 0x66, 0x55); - err += sn9c102_i2c_write(cam, 0x67, 0x01); - err += sn9c102_i2c_write(cam, 0x68, 0xac); - err += sn9c102_i2c_write(cam, 0x69, 0x38); - err += sn9c102_i2c_write(cam, 0x6f, 0x1f); - err += sn9c102_i2c_write(cam, 0x70, 0x01); - err += sn9c102_i2c_write(cam, 0x71, 0x00); - err += sn9c102_i2c_write(cam, 0x72, 0x10); - err += sn9c102_i2c_write(cam, 0x73, 0x50); - err += sn9c102_i2c_write(cam, 0x74, 0x20); - err += sn9c102_i2c_write(cam, 0x76, 0x01); - err += sn9c102_i2c_write(cam, 0x77, 0xf3); - err += sn9c102_i2c_write(cam, 0x78, 0x90); - err += sn9c102_i2c_write(cam, 0x79, 0x98); - err += sn9c102_i2c_write(cam, 0x7a, 0x98); - err += sn9c102_i2c_write(cam, 0x7b, 0x00); - err += sn9c102_i2c_write(cam, 0x7c, 0x38); - err += sn9c102_i2c_write(cam, 0x7d, 0xff); - break; - default: - break; - } - - return err; -} - - -static int ov7630_get_ctrl(struct sn9c102_device *cam, - struct v4l2_control *ctrl) -{ - enum sn9c102_bridge bridge = sn9c102_get_bridge(cam); - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - ctrl->value = sn9c102_i2c_read(cam, 0x10); - if (ctrl->value < 0) - return -EIO; - break; - case V4L2_CID_RED_BALANCE: - if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120) - ctrl->value = sn9c102_pread_reg(cam, 0x05); - else - ctrl->value = sn9c102_pread_reg(cam, 0x07); - break; - case V4L2_CID_BLUE_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x06); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120) - ctrl->value = sn9c102_pread_reg(cam, 0x07); - else - ctrl->value = sn9c102_pread_reg(cam, 0x05); - break; - break; - case V4L2_CID_GAIN: - ctrl->value = sn9c102_i2c_read(cam, 0x00); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x3f; - break; - case V4L2_CID_DO_WHITE_BALANCE: - ctrl->value = sn9c102_i2c_read(cam, 0x0c); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x3f; - break; - case V4L2_CID_WHITENESS: - ctrl->value = sn9c102_i2c_read(cam, 0x0d); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x3f; - break; - case V4L2_CID_AUTOGAIN: - ctrl->value = sn9c102_i2c_read(cam, 0x13); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x01; - break; - case V4L2_CID_VFLIP: - ctrl->value = sn9c102_i2c_read(cam, 0x75); - if (ctrl->value < 0) - return -EIO; - ctrl->value = (ctrl->value & 0x80) ? 1 : 0; - break; - case SN9C102_V4L2_CID_GAMMA: - ctrl->value = sn9c102_i2c_read(cam, 0x14); - if (ctrl->value < 0) - return -EIO; - ctrl->value = (ctrl->value & 0x02) ? 1 : 0; - break; - case SN9C102_V4L2_CID_BAND_FILTER: - ctrl->value = sn9c102_i2c_read(cam, 0x2d); - if (ctrl->value < 0) - return -EIO; - ctrl->value = (ctrl->value & 0x02) ? 1 : 0; - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int ov7630_set_ctrl(struct sn9c102_device *cam, - const struct v4l2_control *ctrl) -{ - enum sn9c102_bridge bridge = sn9c102_get_bridge(cam); - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x10, ctrl->value); - break; - case V4L2_CID_RED_BALANCE: - if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120) - err += sn9c102_write_reg(cam, ctrl->value, 0x05); - else - err += sn9c102_write_reg(cam, ctrl->value, 0x07); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_write_reg(cam, ctrl->value, 0x06); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120) - err += sn9c102_write_reg(cam, ctrl->value, 0x07); - else - err += sn9c102_write_reg(cam, ctrl->value, 0x05); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x00, ctrl->value); - break; - case V4L2_CID_DO_WHITE_BALANCE: - err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); - break; - case V4L2_CID_WHITENESS: - err += sn9c102_i2c_write(cam, 0x0d, ctrl->value); - break; - case V4L2_CID_AUTOGAIN: - err += sn9c102_i2c_write(cam, 0x13, ctrl->value | - (ctrl->value << 1)); - break; - case V4L2_CID_VFLIP: - err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7)); - break; - case SN9C102_V4L2_CID_GAMMA: - err += sn9c102_i2c_write(cam, 0x14, ctrl->value << 2); - break; - case SN9C102_V4L2_CID_BAND_FILTER: - err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int ov7630_set_crop(struct sn9c102_device *cam, - const struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1; - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4; - break; - default: - break; - } - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int ov7630_set_pix_format(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix) -{ - int err = 0; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) - err += sn9c102_write_reg(cam, 0x50, 0x19); - else - err += sn9c102_write_reg(cam, 0x20, 0x19); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { - err += sn9c102_write_reg(cam, 0xe5, 0x17); - err += sn9c102_i2c_write(cam, 0x11, 0x04); - } else { - err += sn9c102_write_reg(cam, 0xe2, 0x17); - err += sn9c102_i2c_write(cam, 0x11, 0x02); - } - break; - default: - break; - } - - return err; -} - - -static const struct sn9c102_sensor ov7630 = { - .name = "OV7630", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103 | - BRIDGE_SN9C105 | BRIDGE_SN9C120, - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x21, - .init = &ov7630_init, - .qctrl = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x14, - .flags = 0, - }, - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0x60, - .flags = 0, - }, - { - .id = V4L2_CID_WHITENESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "white balance background: red", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = V4L2_CID_DO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "white balance background: blue", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto adjust", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x01, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_BAND_FILTER, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "band filter", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GAMMA, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "rgb gamma", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - }, - .get_ctrl = &ov7630_get_ctrl, - .set_ctrl = &ov7630_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &ov7630_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SN9C10X, - .priv = 8, - }, - .set_pix_format = &ov7630_set_pix_format -}; - - -int sn9c102_probe_ov7630(struct sn9c102_device *cam) -{ - int pid, ver, err = 0; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, - {0x28, 0x17}); - break; - case BRIDGE_SN9C103: /* do _not_ change anything! */ - err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x42, 0x01}, - {0x28, 0x17}, {0x44, 0x02}); - pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a); - if (err || pid < 0) /* try a different initialization */ - err += sn9c102_write_const_regs(cam, {0x01, 0x01}, - {0x00, 0x01}); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1}, - {0x29, 0x01}, {0x74, 0x02}, - {0x0e, 0x01}, {0x44, 0x01}); - break; - default: - break; - } - - pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a); - ver = sn9c102_i2c_try_read(cam, &ov7630, 0x0b); - if (err || pid < 0 || ver < 0) - return -EIO; - if (pid != 0x76 || ver != 0x31) - return -ENODEV; - sn9c102_attach_sensor(cam, &ov7630); - - return 0; -} diff --git a/drivers/staging/media/sn9c102/sn9c102_ov7660.c b/drivers/staging/media/sn9c102/sn9c102_ov7660.c deleted file mode 100644 index ac07805d122e..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_ov7660.c +++ /dev/null @@ -1,546 +0,0 @@ -/*************************************************************************** - * Plug-in for OV7660 image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int ov7660_init(struct sn9c102_device *cam) -{ - int err = 0; - - err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03}, - {0x1a, 0x04}, {0x03, 0x10}, - {0x08, 0x14}, {0x20, 0x17}, - {0x8b, 0x18}, {0x00, 0x19}, - {0x1d, 0x1a}, {0x10, 0x1b}, - {0x02, 0x1c}, {0x03, 0x1d}, - {0x0f, 0x1e}, {0x0c, 0x1f}, - {0x00, 0x20}, {0x29, 0x21}, - {0x40, 0x22}, {0x54, 0x23}, - {0x66, 0x24}, {0x76, 0x25}, - {0x85, 0x26}, {0x94, 0x27}, - {0xa1, 0x28}, {0xae, 0x29}, - {0xbb, 0x2a}, {0xc7, 0x2b}, - {0xd3, 0x2c}, {0xde, 0x2d}, - {0xea, 0x2e}, {0xf4, 0x2f}, - {0xff, 0x30}, {0x00, 0x3f}, - {0xc7, 0x40}, {0x01, 0x41}, - {0x44, 0x42}, {0x00, 0x43}, - {0x44, 0x44}, {0x00, 0x45}, - {0x44, 0x46}, {0x00, 0x47}, - {0xc7, 0x48}, {0x01, 0x49}, - {0xc7, 0x4a}, {0x01, 0x4b}, - {0xc7, 0x4c}, {0x01, 0x4d}, - {0x44, 0x4e}, {0x00, 0x4f}, - {0x44, 0x50}, {0x00, 0x51}, - {0x44, 0x52}, {0x00, 0x53}, - {0xc7, 0x54}, {0x01, 0x55}, - {0xc7, 0x56}, {0x01, 0x57}, - {0xc7, 0x58}, {0x01, 0x59}, - {0x44, 0x5a}, {0x00, 0x5b}, - {0x44, 0x5c}, {0x00, 0x5d}, - {0x44, 0x5e}, {0x00, 0x5f}, - {0xc7, 0x60}, {0x01, 0x61}, - {0xc7, 0x62}, {0x01, 0x63}, - {0xc7, 0x64}, {0x01, 0x65}, - {0x44, 0x66}, {0x00, 0x67}, - {0x44, 0x68}, {0x00, 0x69}, - {0x44, 0x6a}, {0x00, 0x6b}, - {0xc7, 0x6c}, {0x01, 0x6d}, - {0xc7, 0x6e}, {0x01, 0x6f}, - {0xc7, 0x70}, {0x01, 0x71}, - {0x44, 0x72}, {0x00, 0x73}, - {0x44, 0x74}, {0x00, 0x75}, - {0x44, 0x76}, {0x00, 0x77}, - {0xc7, 0x78}, {0x01, 0x79}, - {0xc7, 0x7a}, {0x01, 0x7b}, - {0xc7, 0x7c}, {0x01, 0x7d}, - {0x44, 0x7e}, {0x00, 0x7f}, - {0x14, 0x84}, {0x00, 0x85}, - {0x27, 0x86}, {0x00, 0x87}, - {0x07, 0x88}, {0x00, 0x89}, - {0xec, 0x8a}, {0x0f, 0x8b}, - {0xd8, 0x8c}, {0x0f, 0x8d}, - {0x3d, 0x8e}, {0x00, 0x8f}, - {0x3d, 0x90}, {0x00, 0x91}, - {0xcd, 0x92}, {0x0f, 0x93}, - {0xf7, 0x94}, {0x0f, 0x95}, - {0x0c, 0x96}, {0x00, 0x97}, - {0x00, 0x98}, {0x66, 0x99}, - {0x05, 0x9a}, {0x00, 0x9b}, - {0x04, 0x9c}, {0x00, 0x9d}, - {0x08, 0x9e}, {0x00, 0x9f}, - {0x2d, 0xc0}, {0x2d, 0xc1}, - {0x3a, 0xc2}, {0x05, 0xc3}, - {0x04, 0xc4}, {0x3f, 0xc5}, - {0x00, 0xc6}, {0x00, 0xc7}, - {0x50, 0xc8}, {0x3C, 0xc9}, - {0x28, 0xca}, {0xd8, 0xcb}, - {0x14, 0xcc}, {0xec, 0xcd}, - {0x32, 0xce}, {0xdd, 0xcf}, - {0x32, 0xd0}, {0xdd, 0xd1}, - {0x6a, 0xd2}, {0x50, 0xd3}, - {0x00, 0xd4}, {0x00, 0xd5}, - {0x00, 0xd6}); - - err += sn9c102_i2c_write(cam, 0x12, 0x80); - err += sn9c102_i2c_write(cam, 0x11, 0x09); - err += sn9c102_i2c_write(cam, 0x00, 0x0A); - err += sn9c102_i2c_write(cam, 0x01, 0x80); - err += sn9c102_i2c_write(cam, 0x02, 0x80); - err += sn9c102_i2c_write(cam, 0x03, 0x00); - err += sn9c102_i2c_write(cam, 0x04, 0x00); - err += sn9c102_i2c_write(cam, 0x05, 0x08); - err += sn9c102_i2c_write(cam, 0x06, 0x0B); - err += sn9c102_i2c_write(cam, 0x07, 0x00); - err += sn9c102_i2c_write(cam, 0x08, 0x1C); - err += sn9c102_i2c_write(cam, 0x09, 0x01); - err += sn9c102_i2c_write(cam, 0x0A, 0x76); - err += sn9c102_i2c_write(cam, 0x0B, 0x60); - err += sn9c102_i2c_write(cam, 0x0C, 0x00); - err += sn9c102_i2c_write(cam, 0x0D, 0x08); - err += sn9c102_i2c_write(cam, 0x0E, 0x04); - err += sn9c102_i2c_write(cam, 0x0F, 0x6F); - err += sn9c102_i2c_write(cam, 0x10, 0x20); - err += sn9c102_i2c_write(cam, 0x11, 0x03); - err += sn9c102_i2c_write(cam, 0x12, 0x05); - err += sn9c102_i2c_write(cam, 0x13, 0xC7); - err += sn9c102_i2c_write(cam, 0x14, 0x2C); - err += sn9c102_i2c_write(cam, 0x15, 0x00); - err += sn9c102_i2c_write(cam, 0x16, 0x02); - err += sn9c102_i2c_write(cam, 0x17, 0x10); - err += sn9c102_i2c_write(cam, 0x18, 0x60); - err += sn9c102_i2c_write(cam, 0x19, 0x02); - err += sn9c102_i2c_write(cam, 0x1A, 0x7B); - err += sn9c102_i2c_write(cam, 0x1B, 0x02); - err += sn9c102_i2c_write(cam, 0x1C, 0x7F); - err += sn9c102_i2c_write(cam, 0x1D, 0xA2); - err += sn9c102_i2c_write(cam, 0x1E, 0x01); - err += sn9c102_i2c_write(cam, 0x1F, 0x0E); - err += sn9c102_i2c_write(cam, 0x20, 0x05); - err += sn9c102_i2c_write(cam, 0x21, 0x05); - err += sn9c102_i2c_write(cam, 0x22, 0x05); - err += sn9c102_i2c_write(cam, 0x23, 0x05); - err += sn9c102_i2c_write(cam, 0x24, 0x68); - err += sn9c102_i2c_write(cam, 0x25, 0x58); - err += sn9c102_i2c_write(cam, 0x26, 0xD4); - err += sn9c102_i2c_write(cam, 0x27, 0x80); - err += sn9c102_i2c_write(cam, 0x28, 0x80); - err += sn9c102_i2c_write(cam, 0x29, 0x30); - err += sn9c102_i2c_write(cam, 0x2A, 0x00); - err += sn9c102_i2c_write(cam, 0x2B, 0x00); - err += sn9c102_i2c_write(cam, 0x2C, 0x80); - err += sn9c102_i2c_write(cam, 0x2D, 0x00); - err += sn9c102_i2c_write(cam, 0x2E, 0x00); - err += sn9c102_i2c_write(cam, 0x2F, 0x0E); - err += sn9c102_i2c_write(cam, 0x30, 0x08); - err += sn9c102_i2c_write(cam, 0x31, 0x30); - err += sn9c102_i2c_write(cam, 0x32, 0xB4); - err += sn9c102_i2c_write(cam, 0x33, 0x00); - err += sn9c102_i2c_write(cam, 0x34, 0x07); - err += sn9c102_i2c_write(cam, 0x35, 0x84); - err += sn9c102_i2c_write(cam, 0x36, 0x00); - err += sn9c102_i2c_write(cam, 0x37, 0x0C); - err += sn9c102_i2c_write(cam, 0x38, 0x02); - err += sn9c102_i2c_write(cam, 0x39, 0x43); - err += sn9c102_i2c_write(cam, 0x3A, 0x00); - err += sn9c102_i2c_write(cam, 0x3B, 0x0A); - err += sn9c102_i2c_write(cam, 0x3C, 0x6C); - err += sn9c102_i2c_write(cam, 0x3D, 0x99); - err += sn9c102_i2c_write(cam, 0x3E, 0x0E); - err += sn9c102_i2c_write(cam, 0x3F, 0x41); - err += sn9c102_i2c_write(cam, 0x40, 0xC1); - err += sn9c102_i2c_write(cam, 0x41, 0x22); - err += sn9c102_i2c_write(cam, 0x42, 0x08); - err += sn9c102_i2c_write(cam, 0x43, 0xF0); - err += sn9c102_i2c_write(cam, 0x44, 0x10); - err += sn9c102_i2c_write(cam, 0x45, 0x78); - err += sn9c102_i2c_write(cam, 0x46, 0xA8); - err += sn9c102_i2c_write(cam, 0x47, 0x60); - err += sn9c102_i2c_write(cam, 0x48, 0x80); - err += sn9c102_i2c_write(cam, 0x49, 0x00); - err += sn9c102_i2c_write(cam, 0x4A, 0x00); - err += sn9c102_i2c_write(cam, 0x4B, 0x00); - err += sn9c102_i2c_write(cam, 0x4C, 0x00); - err += sn9c102_i2c_write(cam, 0x4D, 0x00); - err += sn9c102_i2c_write(cam, 0x4E, 0x00); - err += sn9c102_i2c_write(cam, 0x4F, 0x46); - err += sn9c102_i2c_write(cam, 0x50, 0x36); - err += sn9c102_i2c_write(cam, 0x51, 0x0F); - err += sn9c102_i2c_write(cam, 0x52, 0x17); - err += sn9c102_i2c_write(cam, 0x53, 0x7F); - err += sn9c102_i2c_write(cam, 0x54, 0x96); - err += sn9c102_i2c_write(cam, 0x55, 0x40); - err += sn9c102_i2c_write(cam, 0x56, 0x40); - err += sn9c102_i2c_write(cam, 0x57, 0x40); - err += sn9c102_i2c_write(cam, 0x58, 0x0F); - err += sn9c102_i2c_write(cam, 0x59, 0xBA); - err += sn9c102_i2c_write(cam, 0x5A, 0x9A); - err += sn9c102_i2c_write(cam, 0x5B, 0x22); - err += sn9c102_i2c_write(cam, 0x5C, 0xB9); - err += sn9c102_i2c_write(cam, 0x5D, 0x9B); - err += sn9c102_i2c_write(cam, 0x5E, 0x10); - err += sn9c102_i2c_write(cam, 0x5F, 0xF0); - err += sn9c102_i2c_write(cam, 0x60, 0x05); - err += sn9c102_i2c_write(cam, 0x61, 0x60); - err += sn9c102_i2c_write(cam, 0x62, 0x00); - err += sn9c102_i2c_write(cam, 0x63, 0x00); - err += sn9c102_i2c_write(cam, 0x64, 0x50); - err += sn9c102_i2c_write(cam, 0x65, 0x30); - err += sn9c102_i2c_write(cam, 0x66, 0x00); - err += sn9c102_i2c_write(cam, 0x67, 0x80); - err += sn9c102_i2c_write(cam, 0x68, 0x7A); - err += sn9c102_i2c_write(cam, 0x69, 0x90); - err += sn9c102_i2c_write(cam, 0x6A, 0x80); - err += sn9c102_i2c_write(cam, 0x6B, 0x0A); - err += sn9c102_i2c_write(cam, 0x6C, 0x30); - err += sn9c102_i2c_write(cam, 0x6D, 0x48); - err += sn9c102_i2c_write(cam, 0x6E, 0x80); - err += sn9c102_i2c_write(cam, 0x6F, 0x74); - err += sn9c102_i2c_write(cam, 0x70, 0x64); - err += sn9c102_i2c_write(cam, 0x71, 0x60); - err += sn9c102_i2c_write(cam, 0x72, 0x5C); - err += sn9c102_i2c_write(cam, 0x73, 0x58); - err += sn9c102_i2c_write(cam, 0x74, 0x54); - err += sn9c102_i2c_write(cam, 0x75, 0x4C); - err += sn9c102_i2c_write(cam, 0x76, 0x40); - err += sn9c102_i2c_write(cam, 0x77, 0x38); - err += sn9c102_i2c_write(cam, 0x78, 0x34); - err += sn9c102_i2c_write(cam, 0x79, 0x30); - err += sn9c102_i2c_write(cam, 0x7A, 0x2F); - err += sn9c102_i2c_write(cam, 0x7B, 0x2B); - err += sn9c102_i2c_write(cam, 0x7C, 0x03); - err += sn9c102_i2c_write(cam, 0x7D, 0x07); - err += sn9c102_i2c_write(cam, 0x7E, 0x17); - err += sn9c102_i2c_write(cam, 0x7F, 0x34); - err += sn9c102_i2c_write(cam, 0x80, 0x41); - err += sn9c102_i2c_write(cam, 0x81, 0x4D); - err += sn9c102_i2c_write(cam, 0x82, 0x58); - err += sn9c102_i2c_write(cam, 0x83, 0x63); - err += sn9c102_i2c_write(cam, 0x84, 0x6E); - err += sn9c102_i2c_write(cam, 0x85, 0x77); - err += sn9c102_i2c_write(cam, 0x86, 0x87); - err += sn9c102_i2c_write(cam, 0x87, 0x95); - err += sn9c102_i2c_write(cam, 0x88, 0xAF); - err += sn9c102_i2c_write(cam, 0x89, 0xC7); - err += sn9c102_i2c_write(cam, 0x8A, 0xDF); - err += sn9c102_i2c_write(cam, 0x8B, 0x99); - err += sn9c102_i2c_write(cam, 0x8C, 0x99); - err += sn9c102_i2c_write(cam, 0x8D, 0xCF); - err += sn9c102_i2c_write(cam, 0x8E, 0x20); - err += sn9c102_i2c_write(cam, 0x8F, 0x26); - err += sn9c102_i2c_write(cam, 0x90, 0x10); - err += sn9c102_i2c_write(cam, 0x91, 0x0C); - err += sn9c102_i2c_write(cam, 0x92, 0x25); - err += sn9c102_i2c_write(cam, 0x93, 0x00); - err += sn9c102_i2c_write(cam, 0x94, 0x50); - err += sn9c102_i2c_write(cam, 0x95, 0x50); - err += sn9c102_i2c_write(cam, 0x96, 0x00); - err += sn9c102_i2c_write(cam, 0x97, 0x01); - err += sn9c102_i2c_write(cam, 0x98, 0x10); - err += sn9c102_i2c_write(cam, 0x99, 0x40); - err += sn9c102_i2c_write(cam, 0x9A, 0x40); - err += sn9c102_i2c_write(cam, 0x9B, 0x20); - err += sn9c102_i2c_write(cam, 0x9C, 0x00); - err += sn9c102_i2c_write(cam, 0x9D, 0x99); - err += sn9c102_i2c_write(cam, 0x9E, 0x7F); - err += sn9c102_i2c_write(cam, 0x9F, 0x00); - err += sn9c102_i2c_write(cam, 0xA0, 0x00); - err += sn9c102_i2c_write(cam, 0xA1, 0x00); - - return err; -} - - -static int ov7660_get_ctrl(struct sn9c102_device *cam, - struct v4l2_control *ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - ctrl->value = sn9c102_i2c_read(cam, 0x10); - if (ctrl->value < 0) - return -EIO; - break; - case V4L2_CID_DO_WHITE_BALANCE: - ctrl->value = sn9c102_read_reg(cam, 0x02); - if (ctrl->value < 0) - return -EIO; - ctrl->value = (ctrl->value & 0x04) ? 1 : 0; - break; - case V4L2_CID_RED_BALANCE: - ctrl->value = sn9c102_read_reg(cam, 0x05); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x7f; - break; - case V4L2_CID_BLUE_BALANCE: - ctrl->value = sn9c102_read_reg(cam, 0x06); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x7f; - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = sn9c102_read_reg(cam, 0x07); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x7f; - break; - case SN9C102_V4L2_CID_BAND_FILTER: - ctrl->value = sn9c102_i2c_read(cam, 0x3b); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x08; - break; - case V4L2_CID_GAIN: - ctrl->value = sn9c102_i2c_read(cam, 0x00); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x1f; - break; - case V4L2_CID_AUTOGAIN: - ctrl->value = sn9c102_i2c_read(cam, 0x13); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x01; - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int ov7660_set_ctrl(struct sn9c102_device *cam, - const struct v4l2_control *ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x10, ctrl->value); - break; - case V4L2_CID_DO_WHITE_BALANCE: - err += sn9c102_write_reg(cam, 0x43 | (ctrl->value << 2), 0x02); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_write_reg(cam, ctrl->value, 0x05); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_write_reg(cam, ctrl->value, 0x06); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_write_reg(cam, ctrl->value, 0x07); - break; - case SN9C102_V4L2_CID_BAND_FILTER: - err += sn9c102_i2c_write(cam, ctrl->value << 3, 0x3b); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x00, 0x60 + ctrl->value); - break; - case V4L2_CID_AUTOGAIN: - err += sn9c102_i2c_write(cam, 0x13, 0xc0 | - (ctrl->value * 0x07)); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int ov7660_set_crop(struct sn9c102_device *cam, - const struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int ov7660_set_pix_format(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix) -{ - int r0, err = 0; - - r0 = sn9c102_pread_reg(cam, 0x01); - - if (pix->pixelformat == V4L2_PIX_FMT_JPEG) { - err += sn9c102_write_reg(cam, r0 | 0x40, 0x01); - err += sn9c102_write_reg(cam, 0xa2, 0x17); - err += sn9c102_i2c_write(cam, 0x11, 0x00); - } else { - err += sn9c102_write_reg(cam, r0 | 0x40, 0x01); - err += sn9c102_write_reg(cam, 0xa2, 0x17); - err += sn9c102_i2c_write(cam, 0x11, 0x0d); - } - - return err; -} - - -static const struct sn9c102_sensor ov7660 = { - .name = "OV7660", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120, - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x21, - .init = &ov7660_init, - .qctrl = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x09, - .flags = 0, - }, - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0x27, - .flags = 0, - }, - { - .id = V4L2_CID_DO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "night mode", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x14, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x14, - .flags = 0, - }, - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto adjust", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x01, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x14, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_BAND_FILTER, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "band filter", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - }, - .get_ctrl = &ov7660_get_ctrl, - .set_ctrl = &ov7660_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &ov7660_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_JPEG, - .priv = 8, - }, - .set_pix_format = &ov7660_set_pix_format -}; - - -int sn9c102_probe_ov7660(struct sn9c102_device *cam) -{ - int pid, ver, err; - - err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1}, - {0x01, 0x01}, {0x00, 0x01}, - {0x28, 0x17}); - - pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a); - ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b); - if (err || pid < 0 || ver < 0) - return -EIO; - if (pid != 0x76 || ver != 0x60) - return -ENODEV; - - sn9c102_attach_sensor(cam, &ov7660); - - return 0; -} diff --git a/drivers/staging/media/sn9c102/sn9c102_pas106b.c b/drivers/staging/media/sn9c102/sn9c102_pas106b.c deleted file mode 100644 index 895931ecac48..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_pas106b.c +++ /dev/null @@ -1,308 +0,0 @@ -/*************************************************************************** - * Plug-in for PAS106B image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#include <linux/delay.h> -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int pas106b_init(struct sn9c102_device *cam) -{ - int err = 0; - - err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, - {0x00, 0x14}, {0x20, 0x17}, - {0x20, 0x19}, {0x09, 0x18}); - - err += sn9c102_i2c_write(cam, 0x02, 0x0c); - err += sn9c102_i2c_write(cam, 0x05, 0x5a); - err += sn9c102_i2c_write(cam, 0x06, 0x88); - err += sn9c102_i2c_write(cam, 0x07, 0x80); - err += sn9c102_i2c_write(cam, 0x10, 0x06); - err += sn9c102_i2c_write(cam, 0x11, 0x06); - err += sn9c102_i2c_write(cam, 0x12, 0x00); - err += sn9c102_i2c_write(cam, 0x14, 0x02); - err += sn9c102_i2c_write(cam, 0x13, 0x01); - - msleep(400); - - return err; -} - - -static int pas106b_get_ctrl(struct sn9c102_device *cam, - struct v4l2_control *ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - { - int r1 = sn9c102_i2c_read(cam, 0x03), - r2 = sn9c102_i2c_read(cam, 0x04); - if (r1 < 0 || r2 < 0) - return -EIO; - ctrl->value = (r1 << 4) | (r2 & 0x0f); - } - return 0; - case V4L2_CID_RED_BALANCE: - ctrl->value = sn9c102_i2c_read(cam, 0x0c); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; - case V4L2_CID_BLUE_BALANCE: - ctrl->value = sn9c102_i2c_read(cam, 0x09); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; - case V4L2_CID_GAIN: - ctrl->value = sn9c102_i2c_read(cam, 0x0e); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; - case V4L2_CID_CONTRAST: - ctrl->value = sn9c102_i2c_read(cam, 0x0f); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x07; - return 0; - case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = sn9c102_i2c_read(cam, 0x0a); - if (ctrl->value < 0) - return -EIO; - ctrl->value = (ctrl->value & 0x1f) << 1; - return 0; - case SN9C102_V4L2_CID_DAC_MAGNITUDE: - ctrl->value = sn9c102_i2c_read(cam, 0x08); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0xf8; - return 0; - default: - return -EINVAL; - } -} - - -static int pas106b_set_ctrl(struct sn9c102_device *cam, - const struct v4l2_control *ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x03, ctrl->value >> 4); - err += sn9c102_i2c_write(cam, 0x04, ctrl->value & 0x0f); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x09, ctrl->value); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x0e, ctrl->value); - break; - case V4L2_CID_CONTRAST: - err += sn9c102_i2c_write(cam, 0x0f, ctrl->value); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_write(cam, 0x0a, ctrl->value >> 1); - err += sn9c102_i2c_write(cam, 0x0b, ctrl->value >> 1); - break; - case SN9C102_V4L2_CID_DAC_MAGNITUDE: - err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3); - break; - default: - return -EINVAL; - } - err += sn9c102_i2c_write(cam, 0x13, 0x01); - - return err ? -EIO : 0; -} - - -static int pas106b_set_crop(struct sn9c102_device *cam, - const struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int pas106b_set_pix_format(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x2c, 0x17); - else - err += sn9c102_write_reg(cam, 0x20, 0x17); - - return err; -} - - -static const struct sn9c102_sensor pas106b = { - .name = "PAS106B", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x40, - .init = &pas106b_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x125, - .maximum = 0xfff, - .step = 0x001, - .default_value = 0x140, - .flags = 0, - }, - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x0d, - .flags = 0, - }, - { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "contrast", - .minimum = 0x00, - .maximum = 0x07, - .step = 0x01, - .default_value = 0x00, /* 0x00~0x03 have same effect */ - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x04, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x06, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x3e, - .step = 0x02, - .default_value = 0x02, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "DAC magnitude", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x01, - .flags = 0, - }, - }, - .get_ctrl = &pas106b_get_ctrl, - .set_ctrl = &pas106b_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - }, - .set_crop = &pas106b_set_crop, - .pix_format = { - .width = 352, - .height = 288, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, /* we use this field as 'bits per pixel' */ - }, - .set_pix_format = &pas106b_set_pix_format -}; - - -int sn9c102_probe_pas106b(struct sn9c102_device *cam) -{ - int r0 = 0, r1 = 0; - unsigned int pid = 0; - - /* - Minimal initialization to enable the I2C communication - NOTE: do NOT change the values! - */ - if (sn9c102_write_const_regs(cam, - {0x01, 0x01}, /* sensor power down */ - {0x00, 0x01}, /* sensor power on */ - {0x28, 0x17})) /* sensor clock at 24 MHz */ - return -EIO; - - r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00); - r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01); - if (r0 < 0 || r1 < 0) - return -EIO; - - pid = (r0 << 11) | ((r1 & 0xf0) >> 4); - if (pid != 0x007) - return -ENODEV; - - sn9c102_attach_sensor(cam, &pas106b); - - return 0; -} diff --git a/drivers/staging/media/sn9c102/sn9c102_pas202bcb.c b/drivers/staging/media/sn9c102/sn9c102_pas202bcb.c deleted file mode 100644 index f9e31ae2ad9f..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_pas202bcb.c +++ /dev/null @@ -1,340 +0,0 @@ -/*************************************************************************** - * Plug-in for PAS202BCB image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio * - * <medaglia@undl.org.br> * - * * - * Support for SN9C103, DAC Magnitude, exposure and green gain controls * - * added by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#include <linux/delay.h> -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int pas202bcb_init(struct sn9c102_device *cam) -{ - int err = 0; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, - {0x00, 0x14}, {0x20, 0x17}, - {0x30, 0x19}, {0x09, 0x18}); - break; - case BRIDGE_SN9C103: - err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03}, - {0x1a, 0x04}, {0x20, 0x05}, - {0x20, 0x06}, {0x20, 0x07}, - {0x00, 0x10}, {0x00, 0x11}, - {0x00, 0x14}, {0x20, 0x17}, - {0x30, 0x19}, {0x09, 0x18}, - {0x02, 0x1c}, {0x03, 0x1d}, - {0x0f, 0x1e}, {0x0c, 0x1f}, - {0x00, 0x20}, {0x10, 0x21}, - {0x20, 0x22}, {0x30, 0x23}, - {0x40, 0x24}, {0x50, 0x25}, - {0x60, 0x26}, {0x70, 0x27}, - {0x80, 0x28}, {0x90, 0x29}, - {0xa0, 0x2a}, {0xb0, 0x2b}, - {0xc0, 0x2c}, {0xd0, 0x2d}, - {0xe0, 0x2e}, {0xf0, 0x2f}, - {0xff, 0x30}); - break; - default: - break; - } - - err += sn9c102_i2c_write(cam, 0x02, 0x14); - err += sn9c102_i2c_write(cam, 0x03, 0x40); - err += sn9c102_i2c_write(cam, 0x0d, 0x2c); - err += sn9c102_i2c_write(cam, 0x0e, 0x01); - err += sn9c102_i2c_write(cam, 0x0f, 0xa9); - err += sn9c102_i2c_write(cam, 0x10, 0x08); - err += sn9c102_i2c_write(cam, 0x13, 0x63); - err += sn9c102_i2c_write(cam, 0x15, 0x70); - err += sn9c102_i2c_write(cam, 0x11, 0x01); - - msleep(400); - - return err; -} - - -static int pas202bcb_get_ctrl(struct sn9c102_device *cam, - struct v4l2_control *ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - { - int r1 = sn9c102_i2c_read(cam, 0x04), - r2 = sn9c102_i2c_read(cam, 0x05); - if (r1 < 0 || r2 < 0) - return -EIO; - ctrl->value = (r1 << 6) | (r2 & 0x3f); - } - return 0; - case V4L2_CID_RED_BALANCE: - ctrl->value = sn9c102_i2c_read(cam, 0x09); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x0f; - return 0; - case V4L2_CID_BLUE_BALANCE: - ctrl->value = sn9c102_i2c_read(cam, 0x07); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x0f; - return 0; - case V4L2_CID_GAIN: - ctrl->value = sn9c102_i2c_read(cam, 0x10); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; - case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = sn9c102_i2c_read(cam, 0x08); - if (ctrl->value < 0) - return -EIO; - ctrl->value &= 0x0f; - return 0; - case SN9C102_V4L2_CID_DAC_MAGNITUDE: - ctrl->value = sn9c102_i2c_read(cam, 0x0c); - if (ctrl->value < 0) - return -EIO; - return 0; - default: - return -EINVAL; - } -} - - -static int pas202bcb_set_pix_format(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x28, 0x17); - else - err += sn9c102_write_reg(cam, 0x20, 0x17); - - return err; -} - - -static int pas202bcb_set_ctrl(struct sn9c102_device *cam, - const struct v4l2_control *ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6); - err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x09, ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x07, ctrl->value); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x10, ctrl->value); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_write(cam, 0x08, ctrl->value); - break; - case SN9C102_V4L2_CID_DAC_MAGNITUDE: - err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); - break; - default: - return -EINVAL; - } - err += sn9c102_i2c_write(cam, 0x11, 0x01); - - return err ? -EIO : 0; -} - - -static int pas202bcb_set_crop(struct sn9c102_device *cam, - const struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - u8 h_start = 0, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4; - break; - case BRIDGE_SN9C103: - h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3; - break; - default: - break; - } - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static const struct sn9c102_sensor pas202bcb = { - .name = "PAS202BCB", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x40, - .init = &pas202bcb_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x01e5, - .maximum = 0x3fff, - .step = 0x0001, - .default_value = 0x01e5, - .flags = 0, - }, - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x0b, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x05, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "DAC magnitude", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0x04, - .flags = 0, - }, - }, - .get_ctrl = &pas202bcb_get_ctrl, - .set_ctrl = &pas202bcb_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &pas202bcb_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &pas202bcb_set_pix_format -}; - - -int sn9c102_probe_pas202bcb(struct sn9c102_device *cam) -{ - int r0 = 0, r1 = 0, err = 0; - unsigned int pid = 0; - - /* - * Minimal initialization to enable the I2C communication - * NOTE: do NOT change the values! - */ - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - err = sn9c102_write_const_regs(cam, - {0x01, 0x01}, /* power down */ - {0x40, 0x01}, /* power on */ - {0x28, 0x17});/* clock 24 MHz */ - break; - case BRIDGE_SN9C103: /* do _not_ change anything! */ - err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x01}, - {0x44, 0x02}, {0x29, 0x17}); - break; - default: - break; - } - - r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00); - r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01); - - if (err || r0 < 0 || r1 < 0) - return -EIO; - - pid = (r0 << 4) | ((r1 & 0xf0) >> 4); - if (pid != 0x017) - return -ENODEV; - - sn9c102_attach_sensor(cam, &pas202bcb); - - return 0; -} diff --git a/drivers/staging/media/sn9c102/sn9c102_sensor.h b/drivers/staging/media/sn9c102/sn9c102_sensor.h deleted file mode 100644 index 9f59c815d48b..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_sensor.h +++ /dev/null @@ -1,307 +0,0 @@ -/*************************************************************************** - * API for image sensors connected to the SN9C1xx PC Camera Controllers * - * * - * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#ifndef _SN9C102_SENSOR_H_ -#define _SN9C102_SENSOR_H_ - -#include <linux/usb.h> -#include <linux/videodev2.h> -#include <linux/device.h> -#include <linux/stddef.h> -#include <linux/errno.h> -#include <asm/types.h> - -struct sn9c102_device; -struct sn9c102_sensor; - -/*****************************************************************************/ - -/* - OVERVIEW. - This is a small interface that allows you to add support for any CCD/CMOS - image sensors connected to the SN9C1XX bridges. The entire API is documented - below. In the most general case, to support a sensor there are three steps - you have to follow: - 1) define the main "sn9c102_sensor" structure by setting the basic fields; - 2) write a probing function to be called by the core module when the USB - camera is recognized, then add both the USB ids and the name of that - function to the two corresponding tables in sn9c102_devtable.h; - 3) implement the methods that you want/need (and fill the rest of the main - structure accordingly). - "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do - NOT need to touch the source code of the core module for the things to work - properly, unless you find bugs or flaws in it. Finally, do not forget to - read the V4L2 API for completeness. -*/ - -/*****************************************************************************/ - -enum sn9c102_bridge { - BRIDGE_SN9C101 = 0x01, - BRIDGE_SN9C102 = 0x02, - BRIDGE_SN9C103 = 0x04, - BRIDGE_SN9C105 = 0x08, - BRIDGE_SN9C120 = 0x10, -}; - -/* Return the bridge name */ -enum sn9c102_bridge sn9c102_get_bridge(struct sn9c102_device *cam); - -/* Return a pointer the sensor struct attached to the camera */ -struct sn9c102_sensor *sn9c102_get_sensor(struct sn9c102_device *cam); - -/* Identify a device */ -extern struct sn9c102_device* -sn9c102_match_id(struct sn9c102_device *cam, const struct usb_device_id *id); - -/* Attach a probed sensor to the camera. */ -extern void -sn9c102_attach_sensor(struct sn9c102_device *cam, - const struct sn9c102_sensor *sensor); - -/* - Read/write routines: they always return -1 on error, 0 or the read value - otherwise. NOTE that a real read operation is not supported by the SN9C1XX - chip for some of its registers. To work around this problem, a pseudo-read - call is provided instead: it returns the last successfully written value - on the register (0 if it has never been written), the usual -1 on error. -*/ - -/* The "try" I2C I/O versions are used when probing the sensor */ -extern int sn9c102_i2c_try_read(struct sn9c102_device*, - const struct sn9c102_sensor*, u8 address); - -/* - These must be used if and only if the sensor doesn't implement the standard - I2C protocol. There are a number of good reasons why you must use the - single-byte versions of these functions: do not abuse. The first function - writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C1XX - chip. The second one programs the registers 0x09 and 0x10 with data0 and - data1, and places the n bytes read from the sensor register table in the - buffer pointed by 'buffer'. Both the functions return -1 on error; the write - version returns 0 on success, while the read version returns the first read - byte. -*/ -extern int sn9c102_i2c_try_raw_write(struct sn9c102_device *cam, - const struct sn9c102_sensor *sensor, u8 n, - u8 data0, u8 data1, u8 data2, u8 data3, - u8 data4, u8 data5); -extern int sn9c102_i2c_try_raw_read(struct sn9c102_device *cam, - const struct sn9c102_sensor *sensor, - u8 data0, u8 data1, u8 n, u8 buffer[]); - -/* To be used after the sensor struct has been attached to the camera struct */ -extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value); -extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address); - -/* I/O on registers in the bridge. Could be used by the sensor methods too */ -extern int sn9c102_read_reg(struct sn9c102_device*, u16 index); -extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); -extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index); -extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2], - int count); -/* - Write multiple registers with constant values. For example: - sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18}); - Register addresses must be < 256. -*/ -#define sn9c102_write_const_regs(sn9c102_device, data...) \ - ({ static const u8 _valreg[][2] = {data}; \ - sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); }) - -/*****************************************************************************/ - -enum sn9c102_i2c_sysfs_ops { - SN9C102_I2C_READ = 0x01, - SN9C102_I2C_WRITE = 0x02, -}; - -enum sn9c102_i2c_frequency { /* sensors may support both the frequencies */ - SN9C102_I2C_100KHZ = 0x01, - SN9C102_I2C_400KHZ = 0x02, -}; - -enum sn9c102_i2c_interface { - SN9C102_I2C_2WIRES, - SN9C102_I2C_3WIRES, -}; - -#define SN9C102_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10) - -struct sn9c102_sensor { - char name[32], /* sensor name */ - maintainer[64]; /* name of the maintainer <email> */ - - enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */ - - /* Supported operations through the 'sysfs' interface */ - enum sn9c102_i2c_sysfs_ops sysfs_ops; - - /* - These sensor capabilities must be provided if the SN9C1XX controller - needs to communicate through the sensor serial interface by using - at least one of the i2c functions available. - */ - enum sn9c102_i2c_frequency frequency; - enum sn9c102_i2c_interface interface; - - /* - This identifier must be provided if the image sensor implements - the standard I2C protocol. - */ - u8 i2c_slave_id; /* reg. 0x09 */ - - /* - NOTE: Where not noted,most of the functions below are not mandatory. - Set to null if you do not implement them. If implemented, - they must return 0 on success, the proper error otherwise. - */ - - int (*init)(struct sn9c102_device *cam); - /* - This function will be called after the sensor has been attached. - It should be used to initialize the sensor only, but may also - configure part of the SN9C1XX chip if necessary. You don't need to - setup picture settings like brightness, contrast, etc.. here, if - the corresponding controls are implemented (see below), since - they are adjusted in the core driver by calling the set_ctrl() - method after init(), where the arguments are the default values - specified in the v4l2_queryctrl list of supported controls; - Same suggestions apply for other settings, _if_ the corresponding - methods are present; if not, the initialization must configure the - sensor according to the default configuration structures below. - */ - - struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS]; - /* - Optional list of default controls, defined as indicated in the - V4L2 API. Menu type controls are not handled by this interface. - */ - - int (*get_ctrl)(struct sn9c102_device *cam, struct v4l2_control *ctrl); - int (*set_ctrl)(struct sn9c102_device *cam, - const struct v4l2_control *ctrl); - /* - You must implement at least the set_ctrl method if you have defined - the list above. The returned value must follow the V4L2 - specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER - are not supported by this driver, so do not implement them. Also, - you don't have to check whether the passed values are out of bounds, - given that this is done by the core module. - */ - - struct v4l2_cropcap cropcap; - /* - Think the image sensor as a grid of R,G,B monochromatic pixels - disposed according to a particular Bayer pattern, which describes - the complete array of pixels, from (0,0) to (xmax, ymax). We will - use this coordinate system from now on. It is assumed the sensor - chip can be programmed to capture/transmit a subsection of that - array of pixels: we will call this subsection "active window". - It is not always true that the largest achievable active window can - cover the whole array of pixels. The V4L2 API defines another - area called "source rectangle", which, in turn, is a subrectangle of - the active window. The SN9C1XX chip is always programmed to read the - source rectangle. - The bounds of both the active window and the source rectangle are - specified in the cropcap substructures 'bounds' and 'defrect'. - By default, the source rectangle should cover the largest possible - area. Again, it is not always true that the largest source rectangle - can cover the entire active window, although it is a rare case for - the hardware we have. The bounds of the source rectangle _must_ be - multiple of 16 and must use the same coordinate system as indicated - before; their centers shall align initially. - If necessary, the sensor chip must be initialized during init() to - set the bounds of the active sensor window; however, by default, it - usually covers the largest achievable area (maxwidth x maxheight) - of pixels, so no particular initialization is needed, if you have - defined the correct default bounds in the structures. - See the V4L2 API for further details. - NOTE: once you have defined the bounds of the active window - (struct cropcap.bounds) you must not change them.anymore. - Only 'bounds' and 'defrect' fields are mandatory, other fields - will be ignored. - */ - - int (*set_crop)(struct sn9c102_device *cam, - const struct v4l2_rect *rect); - /* - To be called on VIDIOC_C_SETCROP. The core module always calls a - default routine which configures the appropriate SN9C1XX regs (also - scaling), but you may need to override/adjust specific stuff. - 'rect' contains width and height values that are multiple of 16: in - case you override the default function, you always have to program - the chip to match those values; on error return the corresponding - error code without rolling back. - NOTE: in case, you must program the SN9C1XX chip to get rid of - blank pixels or blank lines at the _start_ of each line or - frame after each HSYNC or VSYNC, so that the image starts with - real RGB data (see regs 0x12, 0x13) (having set H_SIZE and, - V_SIZE you don't have to care about blank pixels or blank - lines at the end of each line or frame). - */ - - struct v4l2_pix_format pix_format; - /* - What you have to define here are: 1) initial 'width' and 'height' of - the target rectangle 2) the initial 'pixelformat', which can be - either V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_JPEG (for ompressed video) - or V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate - the number of bits per pixel for uncompressed video, 8 or 9 (despite - the current value of 'pixelformat'). - NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4 - of cropcap.defrect.width and cropcap.defrect.height. I - suggest 1/1. - NOTE 2: The initial compression quality is defined by the first bit - of reg 0x17 during the initialization of the image sensor. - NOTE 3: as said above, you have to program the SN9C1XX chip to get - rid of any blank pixels, so that the output of the sensor - matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). - */ - - int (*set_pix_format)(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix); - /* - To be called on VIDIOC_S_FMT, when switching from the SBGGR8 to - SN9C10X pixel format or viceversa. On error return the corresponding - error code without rolling back. - */ - - /* - Do NOT write to the data below, it's READ ONLY. It is used by the - core module to store successfully updated values of the above - settings, for rollbacks..etc..in case of errors during atomic I/O - */ - struct v4l2_queryctrl _qctrl[SN9C102_MAX_CTRLS]; - struct v4l2_rect _rect; -}; - -/*****************************************************************************/ - -/* Private ioctl's for control settings supported by some image sensors */ -#define SN9C102_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0) -#define SN9C102_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1) -#define SN9C102_V4L2_CID_RESET_LEVEL (V4L2_CID_PRIVATE_BASE + 2) -#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE (V4L2_CID_PRIVATE_BASE + 3) -#define SN9C102_V4L2_CID_GAMMA (V4L2_CID_PRIVATE_BASE + 4) -#define SN9C102_V4L2_CID_BAND_FILTER (V4L2_CID_PRIVATE_BASE + 5) -#define SN9C102_V4L2_CID_BRIGHT_LEVEL (V4L2_CID_PRIVATE_BASE + 6) - -#endif /* _SN9C102_SENSOR_H_ */ diff --git a/drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c b/drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c deleted file mode 100644 index 6a00b626d347..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c +++ /dev/null @@ -1,154 +0,0 @@ -/*************************************************************************** - * Plug-in for TAS5110C1B image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int tas5110c1b_init(struct sn9c102_device *cam) -{ - int err = 0; - - err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x44, 0x01}, - {0x00, 0x10}, {0x00, 0x11}, - {0x0a, 0x14}, {0x60, 0x17}, - {0x06, 0x18}, {0xfb, 0x19}); - - err += sn9c102_i2c_write(cam, 0xc0, 0x80); - - return err; -} - - -static int tas5110c1b_set_ctrl(struct sn9c102_device *cam, - const struct v4l2_control *ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int tas5110c1b_set_crop(struct sn9c102_device *cam, - const struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - /* Don't change ! */ - err += sn9c102_write_reg(cam, 0x14, 0x1a); - err += sn9c102_write_reg(cam, 0x0a, 0x1b); - err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19); - - return err; -} - - -static int tas5110c1b_set_pix_format(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x2b, 0x19); - else - err += sn9c102_write_reg(cam, 0xfb, 0x19); - - return err; -} - - -static const struct sn9c102_sensor tas5110c1b = { - .name = "TAS5110C1B", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, - .sysfs_ops = SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_3WIRES, - .init = &tas5110c1b_init, - .qctrl = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0xf6, - .step = 0x01, - .default_value = 0x40, - .flags = 0, - }, - }, - .set_ctrl = &tas5110c1b_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - }, - .set_crop = &tas5110c1b_set_crop, - .pix_format = { - .width = 352, - .height = 288, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &tas5110c1b_set_pix_format -}; - - -int sn9c102_probe_tas5110c1b(struct sn9c102_device *cam) -{ - const struct usb_device_id tas5110c1b_id_table[] = { - { USB_DEVICE(0x0c45, 0x6001), }, - { USB_DEVICE(0x0c45, 0x6005), }, - { USB_DEVICE(0x0c45, 0x60ab), }, - { } - }; - - /* Sensor detection is based on USB pid/vid */ - if (!sn9c102_match_id(cam, tas5110c1b_id_table)) - return -ENODEV; - - sn9c102_attach_sensor(cam, &tas5110c1b); - - return 0; -} diff --git a/drivers/staging/media/sn9c102/sn9c102_tas5110d.c b/drivers/staging/media/sn9c102/sn9c102_tas5110d.c deleted file mode 100644 index eefbf8670c3e..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_tas5110d.c +++ /dev/null @@ -1,119 +0,0 @@ -/*************************************************************************** - * Plug-in for TAS5110D image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int tas5110d_init(struct sn9c102_device *cam) -{ - int err; - - err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x04, 0x01}, - {0x0a, 0x14}, {0x60, 0x17}, - {0x06, 0x18}, {0xfb, 0x19}); - - err += sn9c102_i2c_write(cam, 0x9a, 0xca); - - return err; -} - - -static int tas5110d_set_crop(struct sn9c102_device *cam, - const struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - err += sn9c102_write_reg(cam, 0x14, 0x1a); - err += sn9c102_write_reg(cam, 0x0a, 0x1b); - - return err; -} - - -static int tas5110d_set_pix_format(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x3b, 0x19); - else - err += sn9c102_write_reg(cam, 0xfb, 0x19); - - return err; -} - - -static const struct sn9c102_sensor tas5110d = { - .name = "TAS5110D", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, - .sysfs_ops = SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x61, - .init = &tas5110d_init, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - }, - .set_crop = &tas5110d_set_crop, - .pix_format = { - .width = 352, - .height = 288, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &tas5110d_set_pix_format -}; - - -int sn9c102_probe_tas5110d(struct sn9c102_device *cam) -{ - const struct usb_device_id tas5110d_id_table[] = { - { USB_DEVICE(0x0c45, 0x6007), }, - { } - }; - - if (!sn9c102_match_id(cam, tas5110d_id_table)) - return -ENODEV; - - sn9c102_attach_sensor(cam, &tas5110d); - - return 0; -} diff --git a/drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c b/drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c deleted file mode 100644 index 725de857de45..000000000000 --- a/drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c +++ /dev/null @@ -1,165 +0,0 @@ -/*************************************************************************** - * Plug-in for TAS5130D1B image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int tas5130d1b_init(struct sn9c102_device *cam) -{ - int err; - - err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x20, 0x17}, - {0x04, 0x01}, {0x01, 0x10}, - {0x00, 0x11}, {0x00, 0x14}, - {0x60, 0x17}, {0x07, 0x18}); - - return err; -} - - -static int tas5130d1b_set_ctrl(struct sn9c102_device *cam, - const struct v4l2_control *ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value); - break; - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int tas5130d1b_set_crop(struct sn9c102_device *cam, - const struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12; - int err = 0; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - /* Do NOT change! */ - err += sn9c102_write_reg(cam, 0x1f, 0x1a); - err += sn9c102_write_reg(cam, 0x1a, 0x1b); - err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19); - - return err; -} - - -static int tas5130d1b_set_pix_format(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x63, 0x19); - else - err += sn9c102_write_reg(cam, 0xf3, 0x19); - - return err; -} - - -static const struct sn9c102_sensor tas5130d1b = { - .name = "TAS5130D1B", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, - .sysfs_ops = SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_3WIRES, - .init = &tas5130d1b_init, - .qctrl = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0xf6, - .step = 0x02, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0x47, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - }, - .set_ctrl = &tas5130d1b_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &tas5130d1b_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &tas5130d1b_set_pix_format -}; - - -int sn9c102_probe_tas5130d1b(struct sn9c102_device *cam) -{ - const struct usb_device_id tas5130d1b_id_table[] = { - { USB_DEVICE(0x0c45, 0x6024), }, - { USB_DEVICE(0x0c45, 0x6025), }, - { USB_DEVICE(0x0c45, 0x60aa), }, - { } - }; - - /* Sensor detection is based on USB pid/vid */ - if (!sn9c102_match_id(cam, tas5130d1b_id_table)) - return -ENODEV; - - sn9c102_attach_sensor(cam, &tas5130d1b); - - return 0; -} diff --git a/drivers/staging/media/solo6x10/Kconfig b/drivers/staging/media/solo6x10/Kconfig deleted file mode 100644 index 6a1906fa1117..000000000000 --- a/drivers/staging/media/solo6x10/Kconfig +++ /dev/null @@ -1,18 +0,0 @@ -config SOLO6X10 - tristate "Bluecherry / Softlogic 6x10 capture cards (MPEG-4/H.264)" - depends on PCI && VIDEO_DEV && SND && I2C - select FONT_SUPPORT - select FONT_8x16 - select VIDEOBUF2_DMA_SG - select VIDEOBUF2_DMA_CONTIG - select SND_PCM - select FONT_8x16 - ---help--- - This driver supports the Bluecherry H.264 and MPEG-4 hardware - compression capture cards and other Softlogic-based ones. - - Following cards have been tested: - * Bluecherry BC-H16480A (PCIe, 16 port, H.264) - * Bluecherry BC-H04120A (PCIe, 4 port, H.264) - * Bluecherry BC-H04120A-MPCI (Mini-PCI, 4 port, H.264) - * Bluecherry BC-04120A (PCIe, 4 port, MPEG-4) diff --git a/drivers/staging/media/solo6x10/Makefile b/drivers/staging/media/solo6x10/Makefile deleted file mode 100644 index 7aae118947b2..000000000000 --- a/drivers/staging/media/solo6x10/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -solo6x10-y := solo6x10-core.o solo6x10-i2c.o solo6x10-p2m.o solo6x10-v4l2.o \ - solo6x10-tw28.o solo6x10-gpio.o solo6x10-disp.o solo6x10-enc.o \ - solo6x10-v4l2-enc.o solo6x10-g723.o solo6x10-eeprom.o - -obj-$(CONFIG_SOLO6X10) += solo6x10.o diff --git a/drivers/staging/media/solo6x10/TODO b/drivers/staging/media/solo6x10/TODO deleted file mode 100644 index 7b8db75b1acb..000000000000 --- a/drivers/staging/media/solo6x10/TODO +++ /dev/null @@ -1,15 +0,0 @@ -- batch up desc requests for more efficient use of p2m? -- encoder on/off controls -- mpeg cid bitrate mode (vbr/cbr) -- mpeg cid bitrate/bitrate-peak -- mpeg encode of user data -- mpeg decode of user data -- implement CID controls for mozaic areas - -- sound - - implement playback via external sound jack - - implement loopback of external sound jack with incoming audio? - - implement pause/resume (make use of in bc-server) - -Please send patches to the linux media list <linux-media@vger.kernel.org> and -Cc Ismael Luceno <ismael.luceno@corp.bluecherry.net>. diff --git a/drivers/staging/media/solo6x10/solo6x10-core.c b/drivers/staging/media/solo6x10/solo6x10-core.c deleted file mode 100644 index f67046955ef6..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-core.c +++ /dev/null @@ -1,709 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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/kernel.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/interrupt.h> -#include <linux/videodev2.h> -#include <linux/delay.h> -#include <linux/sysfs.h> -#include <linux/ktime.h> -#include <linux/slab.h> - -#include "solo6x10.h" -#include "solo6x10-tw28.h" - -MODULE_DESCRIPTION("Softlogic 6x10 MPEG4/H.264/G.723 CODEC V4L2/ALSA Driver"); -MODULE_AUTHOR("Bluecherry <maintainers@bluecherrydvr.com>"); -MODULE_VERSION(SOLO6X10_VERSION); -MODULE_LICENSE("GPL"); - -static unsigned video_nr = -1; -module_param(video_nr, uint, 0644); -MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect (default)"); - -static int full_eeprom; /* default is only top 64B */ -module_param(full_eeprom, uint, 0644); -MODULE_PARM_DESC(full_eeprom, "Allow access to full 128B EEPROM (dangerous)"); - - -static void solo_set_time(struct solo_dev *solo_dev) -{ - struct timespec ts; - - ktime_get_ts(&ts); - - solo_reg_write(solo_dev, SOLO_TIMER_SEC, ts.tv_sec); - solo_reg_write(solo_dev, SOLO_TIMER_USEC, ts.tv_nsec / NSEC_PER_USEC); -} - -static void solo_timer_sync(struct solo_dev *solo_dev) -{ - u32 sec, usec; - struct timespec ts; - long diff; - - if (solo_dev->type != SOLO_DEV_6110) - return; - - if (++solo_dev->time_sync < 60) - return; - - solo_dev->time_sync = 0; - - sec = solo_reg_read(solo_dev, SOLO_TIMER_SEC); - usec = solo_reg_read(solo_dev, SOLO_TIMER_USEC); - - ktime_get_ts(&ts); - - diff = (long)ts.tv_sec - (long)sec; - diff = (diff * 1000000) - + ((long)(ts.tv_nsec / NSEC_PER_USEC) - (long)usec); - - if (diff > 1000 || diff < -1000) { - solo_set_time(solo_dev); - } else if (diff) { - long usec_lsb = solo_dev->usec_lsb; - - usec_lsb -= diff / 4; - if (usec_lsb < 0) - usec_lsb = 0; - else if (usec_lsb > 255) - usec_lsb = 255; - - solo_dev->usec_lsb = usec_lsb; - solo_reg_write(solo_dev, SOLO_TIMER_USEC_LSB, - solo_dev->usec_lsb); - } -} - -static irqreturn_t solo_isr(int irq, void *data) -{ - struct solo_dev *solo_dev = data; - u32 status; - int i; - - status = solo_reg_read(solo_dev, SOLO_IRQ_STAT); - if (!status) - return IRQ_NONE; - - if (status & ~solo_dev->irq_mask) { - solo_reg_write(solo_dev, SOLO_IRQ_STAT, - status & ~solo_dev->irq_mask); - status &= solo_dev->irq_mask; - } - - if (status & SOLO_IRQ_PCI_ERR) - solo_p2m_error_isr(solo_dev); - - for (i = 0; i < SOLO_NR_P2M; i++) - if (status & SOLO_IRQ_P2M(i)) - solo_p2m_isr(solo_dev, i); - - if (status & SOLO_IRQ_IIC) - solo_i2c_isr(solo_dev); - - if (status & SOLO_IRQ_VIDEO_IN) { - solo_video_in_isr(solo_dev); - solo_timer_sync(solo_dev); - } - - if (status & SOLO_IRQ_ENCODER) - solo_enc_v4l2_isr(solo_dev); - - if (status & SOLO_IRQ_G723) - solo_g723_isr(solo_dev); - - /* Clear all interrupts handled */ - solo_reg_write(solo_dev, SOLO_IRQ_STAT, status); - - return IRQ_HANDLED; -} - -static void free_solo_dev(struct solo_dev *solo_dev) -{ - struct pci_dev *pdev; - - if (!solo_dev) - return; - - if (solo_dev->dev.parent) - device_unregister(&solo_dev->dev); - - pdev = solo_dev->pdev; - - /* If we never initialized the PCI device, then nothing else - * below here needs cleanup */ - if (!pdev) { - kfree(solo_dev); - return; - } - - if (solo_dev->reg_base) { - /* Bring down the sub-devices first */ - solo_g723_exit(solo_dev); - solo_enc_v4l2_exit(solo_dev); - solo_enc_exit(solo_dev); - solo_v4l2_exit(solo_dev); - solo_disp_exit(solo_dev); - solo_gpio_exit(solo_dev); - solo_p2m_exit(solo_dev); - solo_i2c_exit(solo_dev); - - /* Now cleanup the PCI device */ - solo_irq_off(solo_dev, ~0); - pci_iounmap(pdev, solo_dev->reg_base); - if (pdev->irq) - free_irq(pdev->irq, solo_dev); - } - - pci_release_regions(pdev); - pci_disable_device(pdev); - v4l2_device_unregister(&solo_dev->v4l2_dev); - pci_set_drvdata(pdev, NULL); - - kfree(solo_dev); -} - -static ssize_t eeprom_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct solo_dev *solo_dev = - container_of(dev, struct solo_dev, dev); - unsigned short *p = (unsigned short *)buf; - int i; - - if (count & 0x1) - dev_warn(dev, "EEPROM Write not aligned (truncating)\n"); - - if (!full_eeprom && count > 64) { - dev_warn(dev, "EEPROM Write truncated to 64 bytes\n"); - count = 64; - } else if (full_eeprom && count > 128) { - dev_warn(dev, "EEPROM Write truncated to 128 bytes\n"); - count = 128; - } - - solo_eeprom_ewen(solo_dev, 1); - - for (i = full_eeprom ? 0 : 32; i < min((int)(full_eeprom ? 64 : 32), - (int)(count / 2)); i++) - solo_eeprom_write(solo_dev, i, cpu_to_be16(p[i])); - - solo_eeprom_ewen(solo_dev, 0); - - return count; -} - -static ssize_t eeprom_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct solo_dev *solo_dev = - container_of(dev, struct solo_dev, dev); - unsigned short *p = (unsigned short *)buf; - int count = (full_eeprom ? 128 : 64); - int i; - - for (i = (full_eeprom ? 0 : 32); i < (count / 2); i++) - p[i] = be16_to_cpu(solo_eeprom_read(solo_dev, i)); - - return count; -} - -static ssize_t p2m_timeouts_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct solo_dev *solo_dev = - container_of(dev, struct solo_dev, dev); - - return sprintf(buf, "%d\n", solo_dev->p2m_timeouts); -} - -static ssize_t sdram_size_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct solo_dev *solo_dev = - container_of(dev, struct solo_dev, dev); - - return sprintf(buf, "%dMegs\n", solo_dev->sdram_size >> 20); -} - -static ssize_t tw28xx_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct solo_dev *solo_dev = - container_of(dev, struct solo_dev, dev); - - return sprintf(buf, "tw2815[%d] tw2864[%d] tw2865[%d]\n", - hweight32(solo_dev->tw2815), - hweight32(solo_dev->tw2864), - hweight32(solo_dev->tw2865)); -} - -static ssize_t input_map_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct solo_dev *solo_dev = - container_of(dev, struct solo_dev, dev); - unsigned int val; - char *out = buf; - - val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_0); - out += sprintf(out, "Channel 0 => Input %d\n", val & 0x1f); - out += sprintf(out, "Channel 1 => Input %d\n", (val >> 5) & 0x1f); - out += sprintf(out, "Channel 2 => Input %d\n", (val >> 10) & 0x1f); - out += sprintf(out, "Channel 3 => Input %d\n", (val >> 15) & 0x1f); - out += sprintf(out, "Channel 4 => Input %d\n", (val >> 20) & 0x1f); - out += sprintf(out, "Channel 5 => Input %d\n", (val >> 25) & 0x1f); - - val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_1); - out += sprintf(out, "Channel 6 => Input %d\n", val & 0x1f); - out += sprintf(out, "Channel 7 => Input %d\n", (val >> 5) & 0x1f); - out += sprintf(out, "Channel 8 => Input %d\n", (val >> 10) & 0x1f); - out += sprintf(out, "Channel 9 => Input %d\n", (val >> 15) & 0x1f); - out += sprintf(out, "Channel 10 => Input %d\n", (val >> 20) & 0x1f); - out += sprintf(out, "Channel 11 => Input %d\n", (val >> 25) & 0x1f); - - val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_2); - out += sprintf(out, "Channel 12 => Input %d\n", val & 0x1f); - out += sprintf(out, "Channel 13 => Input %d\n", (val >> 5) & 0x1f); - out += sprintf(out, "Channel 14 => Input %d\n", (val >> 10) & 0x1f); - out += sprintf(out, "Channel 15 => Input %d\n", (val >> 15) & 0x1f); - out += sprintf(out, "Spot Output => Input %d\n", (val >> 20) & 0x1f); - - return out - buf; -} - -static ssize_t p2m_timeout_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct solo_dev *solo_dev = - container_of(dev, struct solo_dev, dev); - unsigned long ms; - - int ret = kstrtoul(buf, 10, &ms); - if (ret < 0 || ms > 200) - return -EINVAL; - solo_dev->p2m_jiffies = msecs_to_jiffies(ms); - - return count; -} - -static ssize_t p2m_timeout_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct solo_dev *solo_dev = - container_of(dev, struct solo_dev, dev); - - return sprintf(buf, "%ums\n", jiffies_to_msecs(solo_dev->p2m_jiffies)); -} - -static ssize_t intervals_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct solo_dev *solo_dev = - container_of(dev, struct solo_dev, dev); - char *out = buf; - int fps = solo_dev->fps; - int i; - - for (i = 0; i < solo_dev->nr_chans; i++) { - out += sprintf(out, "Channel %d: %d/%d (0x%08x)\n", - i, solo_dev->v4l2_enc[i]->interval, fps, - solo_reg_read(solo_dev, SOLO_CAP_CH_INTV(i))); - } - - return out - buf; -} - -static ssize_t sdram_offsets_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct solo_dev *solo_dev = - container_of(dev, struct solo_dev, dev); - char *out = buf; - - out += sprintf(out, "DISP: 0x%08x @ 0x%08x\n", - SOLO_DISP_EXT_ADDR, - SOLO_DISP_EXT_SIZE); - - out += sprintf(out, "EOSD: 0x%08x @ 0x%08x (0x%08x * %d)\n", - SOLO_EOSD_EXT_ADDR, - SOLO_EOSD_EXT_AREA(solo_dev), - SOLO_EOSD_EXT_SIZE(solo_dev), - SOLO_EOSD_EXT_AREA(solo_dev) / - SOLO_EOSD_EXT_SIZE(solo_dev)); - - out += sprintf(out, "MOTI: 0x%08x @ 0x%08x\n", - SOLO_MOTION_EXT_ADDR(solo_dev), - SOLO_MOTION_EXT_SIZE); - - out += sprintf(out, "G723: 0x%08x @ 0x%08x\n", - SOLO_G723_EXT_ADDR(solo_dev), - SOLO_G723_EXT_SIZE); - - out += sprintf(out, "CAPT: 0x%08x @ 0x%08x (0x%08x * %d)\n", - SOLO_CAP_EXT_ADDR(solo_dev), - SOLO_CAP_EXT_SIZE(solo_dev), - SOLO_CAP_PAGE_SIZE, - SOLO_CAP_EXT_SIZE(solo_dev) / SOLO_CAP_PAGE_SIZE); - - out += sprintf(out, "EREF: 0x%08x @ 0x%08x (0x%08x * %d)\n", - SOLO_EREF_EXT_ADDR(solo_dev), - SOLO_EREF_EXT_AREA(solo_dev), - SOLO_EREF_EXT_SIZE, - SOLO_EREF_EXT_AREA(solo_dev) / SOLO_EREF_EXT_SIZE); - - out += sprintf(out, "MPEG: 0x%08x @ 0x%08x\n", - SOLO_MP4E_EXT_ADDR(solo_dev), - SOLO_MP4E_EXT_SIZE(solo_dev)); - - out += sprintf(out, "JPEG: 0x%08x @ 0x%08x\n", - SOLO_JPEG_EXT_ADDR(solo_dev), - SOLO_JPEG_EXT_SIZE(solo_dev)); - - return out - buf; -} - -static ssize_t sdram_show(struct file *file, struct kobject *kobj, - struct bin_attribute *a, char *buf, - loff_t off, size_t count) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct solo_dev *solo_dev = - container_of(dev, struct solo_dev, dev); - const int size = solo_dev->sdram_size; - - if (off >= size) - return 0; - - if (off + count > size) - count = size - off; - - if (solo_p2m_dma(solo_dev, 0, buf, off, count, 0, 0)) - return -EIO; - - return count; -} - -static const struct device_attribute solo_dev_attrs[] = { - __ATTR(eeprom, 0640, eeprom_show, eeprom_store), - __ATTR(p2m_timeout, 0644, p2m_timeout_show, p2m_timeout_store), - __ATTR_RO(p2m_timeouts), - __ATTR_RO(sdram_size), - __ATTR_RO(tw28xx), - __ATTR_RO(input_map), - __ATTR_RO(intervals), - __ATTR_RO(sdram_offsets), -}; - -static void solo_device_release(struct device *dev) -{ - /* Do nothing */ -} - -static int solo_sysfs_init(struct solo_dev *solo_dev) -{ - struct bin_attribute *sdram_attr = &solo_dev->sdram_attr; - struct device *dev = &solo_dev->dev; - const char *driver; - int i; - - if (solo_dev->type == SOLO_DEV_6110) - driver = "solo6110"; - else - driver = "solo6010"; - - dev->release = solo_device_release; - dev->parent = &solo_dev->pdev->dev; - set_dev_node(dev, dev_to_node(&solo_dev->pdev->dev)); - dev_set_name(dev, "%s-%d-%d", driver, solo_dev->vfd->num, - solo_dev->nr_chans); - - if (device_register(dev)) { - dev->parent = NULL; - return -ENOMEM; - } - - for (i = 0; i < ARRAY_SIZE(solo_dev_attrs); i++) { - if (device_create_file(dev, &solo_dev_attrs[i])) { - device_unregister(dev); - return -ENOMEM; - } - } - - sysfs_attr_init(&sdram_attr->attr); - sdram_attr->attr.name = "sdram"; - sdram_attr->attr.mode = 0440; - sdram_attr->read = sdram_show; - sdram_attr->size = solo_dev->sdram_size; - - if (device_create_bin_file(dev, sdram_attr)) { - device_unregister(dev); - return -ENOMEM; - } - - return 0; -} - -static int solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - struct solo_dev *solo_dev; - int ret; - u8 chip_id; - - solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL); - if (solo_dev == NULL) - return -ENOMEM; - - if (id->driver_data == SOLO_DEV_6010) - dev_info(&pdev->dev, "Probing Softlogic 6010\n"); - else - dev_info(&pdev->dev, "Probing Softlogic 6110\n"); - - solo_dev->type = id->driver_data; - solo_dev->pdev = pdev; - spin_lock_init(&solo_dev->reg_io_lock); - ret = v4l2_device_register(&pdev->dev, &solo_dev->v4l2_dev); - if (ret) - goto fail_probe; - - /* Only for during init */ - solo_dev->p2m_jiffies = msecs_to_jiffies(100); - - ret = pci_enable_device(pdev); - if (ret) - goto fail_probe; - - pci_set_master(pdev); - - /* RETRY/TRDY Timeout disabled */ - pci_write_config_byte(pdev, 0x40, 0x00); - pci_write_config_byte(pdev, 0x41, 0x00); - - ret = pci_request_regions(pdev, SOLO6X10_NAME); - if (ret) - goto fail_probe; - - solo_dev->reg_base = pci_ioremap_bar(pdev, 0); - if (solo_dev->reg_base == NULL) { - ret = -ENOMEM; - goto fail_probe; - } - - chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) & - SOLO_CHIP_ID_MASK; - switch (chip_id) { - case 7: - solo_dev->nr_chans = 16; - solo_dev->nr_ext = 5; - break; - case 6: - solo_dev->nr_chans = 8; - solo_dev->nr_ext = 2; - break; - default: - dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, assuming 4 ch\n", - chip_id); - case 5: - solo_dev->nr_chans = 4; - solo_dev->nr_ext = 1; - } - - /* Disable all interrupts to start */ - solo_irq_off(solo_dev, ~0); - - /* Initial global settings */ - if (solo_dev->type == SOLO_DEV_6010) { - solo_dev->clock_mhz = 108; - solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT - | SOLO_SYS_CFG_INPUTDIV(25) - | SOLO_SYS_CFG_FEEDBACKDIV(solo_dev->clock_mhz * 2 - 2) - | SOLO_SYS_CFG_OUTDIV(3); - solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config); - } else { - u32 divq, divf; - - solo_dev->clock_mhz = 135; - - if (solo_dev->clock_mhz < 125) { - divq = 3; - divf = (solo_dev->clock_mhz * 4) / 3 - 1; - } else { - divq = 2; - divf = (solo_dev->clock_mhz * 2) / 3 - 1; - } - - solo_reg_write(solo_dev, SOLO_PLL_CONFIG, - (1 << 20) | /* PLL_RANGE */ - (8 << 15) | /* PLL_DIVR */ - (divq << 12) | - (divf << 4) | - (1 << 1) /* PLL_FSEN */); - - solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT; - } - - solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config); - solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM, - solo_dev->clock_mhz - 1); - - /* PLL locking time of 1ms */ - mdelay(1); - - ret = request_irq(pdev->irq, solo_isr, IRQF_SHARED, SOLO6X10_NAME, - solo_dev); - if (ret) - goto fail_probe; - - /* Handle this from the start */ - solo_irq_on(solo_dev, SOLO_IRQ_PCI_ERR); - - ret = solo_i2c_init(solo_dev); - if (ret) - goto fail_probe; - - /* Setup the DMA engine */ - solo_reg_write(solo_dev, SOLO_DMA_CTRL, - SOLO_DMA_CTRL_REFRESH_CYCLE(1) | - SOLO_DMA_CTRL_SDRAM_SIZE(2) | - SOLO_DMA_CTRL_SDRAM_CLK_INVERT | - SOLO_DMA_CTRL_READ_CLK_SELECT | - SOLO_DMA_CTRL_LATENCY(1)); - - /* Undocumented crap */ - solo_reg_write(solo_dev, SOLO_DMA_CTRL1, - solo_dev->type == SOLO_DEV_6010 ? 0x100 : 0x300); - - if (solo_dev->type != SOLO_DEV_6010) { - solo_dev->usec_lsb = 0x3f; - solo_set_time(solo_dev); - } - - /* Disable watchdog */ - solo_reg_write(solo_dev, SOLO_WATCHDOG, 0); - - /* Initialize sub components */ - - ret = solo_p2m_init(solo_dev); - if (ret) - goto fail_probe; - - ret = solo_disp_init(solo_dev); - if (ret) - goto fail_probe; - - ret = solo_gpio_init(solo_dev); - if (ret) - goto fail_probe; - - ret = solo_tw28_init(solo_dev); - if (ret) - goto fail_probe; - - ret = solo_v4l2_init(solo_dev, video_nr); - if (ret) - goto fail_probe; - - ret = solo_enc_init(solo_dev); - if (ret) - goto fail_probe; - - ret = solo_enc_v4l2_init(solo_dev, video_nr); - if (ret) - goto fail_probe; - - ret = solo_g723_init(solo_dev); - if (ret) - goto fail_probe; - - ret = solo_sysfs_init(solo_dev); - if (ret) - goto fail_probe; - - /* Now that init is over, set this lower */ - solo_dev->p2m_jiffies = msecs_to_jiffies(20); - - return 0; - -fail_probe: - free_solo_dev(solo_dev); - return ret; -} - -static void solo_pci_remove(struct pci_dev *pdev) -{ - struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev); - struct solo_dev *solo_dev = container_of(v4l2_dev, struct solo_dev, v4l2_dev); - - free_solo_dev(solo_dev); -} - -static const struct pci_device_id solo_id_table[] = { - /* 6010 based cards */ - { PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010), - .driver_data = SOLO_DEV_6010 }, - { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4), - .driver_data = SOLO_DEV_6010 }, - { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9), - .driver_data = SOLO_DEV_6010 }, - { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16), - .driver_data = SOLO_DEV_6010 }, - { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4), - .driver_data = SOLO_DEV_6010 }, - { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9), - .driver_data = SOLO_DEV_6010 }, - { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16), - .driver_data = SOLO_DEV_6010 }, - /* 6110 based cards */ - { PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110), - .driver_data = SOLO_DEV_6110 }, - { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4), - .driver_data = SOLO_DEV_6110 }, - { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8), - .driver_data = SOLO_DEV_6110 }, - { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16), - .driver_data = SOLO_DEV_6110 }, - {0,} -}; - -MODULE_DEVICE_TABLE(pci, solo_id_table); - -static struct pci_driver solo_pci_driver = { - .name = SOLO6X10_NAME, - .id_table = solo_id_table, - .probe = solo_pci_probe, - .remove = solo_pci_remove, -}; - -module_pci_driver(solo_pci_driver); diff --git a/drivers/staging/media/solo6x10/solo6x10-disp.c b/drivers/staging/media/solo6x10/solo6x10-disp.c deleted file mode 100644 index 145295a5db72..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-disp.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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/kernel.h> -#include <linux/module.h> -#include <linux/videodev2.h> -#include <media/v4l2-ioctl.h> - -#include "solo6x10.h" - -#define SOLO_VCLK_DELAY 3 -#define SOLO_PROGRESSIVE_VSIZE 1024 - -#define SOLO_MOT_THRESH_W 64 -#define SOLO_MOT_THRESH_H 64 -#define SOLO_MOT_THRESH_SIZE 8192 -#define SOLO_MOT_THRESH_REAL (SOLO_MOT_THRESH_W * SOLO_MOT_THRESH_H) -#define SOLO_MOT_FLAG_SIZE 1024 -#define SOLO_MOT_FLAG_AREA (SOLO_MOT_FLAG_SIZE * 16) - -static void solo_vin_config(struct solo_dev *solo_dev) -{ - solo_dev->vin_hstart = 8; - solo_dev->vin_vstart = 2; - - solo_reg_write(solo_dev, SOLO_SYS_VCLK, - SOLO_VCLK_SELECT(2) | - SOLO_VCLK_VIN1415_DELAY(SOLO_VCLK_DELAY) | - SOLO_VCLK_VIN1213_DELAY(SOLO_VCLK_DELAY) | - SOLO_VCLK_VIN1011_DELAY(SOLO_VCLK_DELAY) | - SOLO_VCLK_VIN0809_DELAY(SOLO_VCLK_DELAY) | - SOLO_VCLK_VIN0607_DELAY(SOLO_VCLK_DELAY) | - SOLO_VCLK_VIN0405_DELAY(SOLO_VCLK_DELAY) | - SOLO_VCLK_VIN0203_DELAY(SOLO_VCLK_DELAY) | - SOLO_VCLK_VIN0001_DELAY(SOLO_VCLK_DELAY)); - - solo_reg_write(solo_dev, SOLO_VI_ACT_I_P, - SOLO_VI_H_START(solo_dev->vin_hstart) | - SOLO_VI_V_START(solo_dev->vin_vstart) | - SOLO_VI_V_STOP(solo_dev->vin_vstart + - solo_dev->video_vsize)); - - solo_reg_write(solo_dev, SOLO_VI_ACT_I_S, - SOLO_VI_H_START(solo_dev->vout_hstart) | - SOLO_VI_V_START(solo_dev->vout_vstart) | - SOLO_VI_V_STOP(solo_dev->vout_vstart + - solo_dev->video_vsize)); - - solo_reg_write(solo_dev, SOLO_VI_ACT_P, - SOLO_VI_H_START(0) | - SOLO_VI_V_START(1) | - SOLO_VI_V_STOP(SOLO_PROGRESSIVE_VSIZE)); - - solo_reg_write(solo_dev, SOLO_VI_CH_FORMAT, - SOLO_VI_FD_SEL_MASK(0) | SOLO_VI_PROG_MASK(0)); - - /* On 6110, initialize mozaic darkness stength */ - if (solo_dev->type == SOLO_DEV_6010) - solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 0); - else - solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 16 << 22); - - solo_reg_write(solo_dev, SOLO_VI_PAGE_SW, 2); - - if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) { - solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG, - SOLO_VI_PB_USER_MODE); - solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV, - SOLO_VI_PB_HSIZE(858) | SOLO_VI_PB_VSIZE(246)); - solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V, - SOLO_VI_PB_VSTART(4) | - SOLO_VI_PB_VSTOP(4 + 240)); - } else { - solo_reg_write(solo_dev, SOLO_VI_PB_CONFIG, - SOLO_VI_PB_USER_MODE | SOLO_VI_PB_PAL); - solo_reg_write(solo_dev, SOLO_VI_PB_RANGE_HV, - SOLO_VI_PB_HSIZE(864) | SOLO_VI_PB_VSIZE(294)); - solo_reg_write(solo_dev, SOLO_VI_PB_ACT_V, - SOLO_VI_PB_VSTART(4) | - SOLO_VI_PB_VSTOP(4 + 288)); - } - solo_reg_write(solo_dev, SOLO_VI_PB_ACT_H, SOLO_VI_PB_HSTART(16) | - SOLO_VI_PB_HSTOP(16 + 720)); -} - -static void solo_vout_config_cursor(struct solo_dev *dev) -{ - int i; - - /* Load (blank) cursor bitmap mask (2bpp) */ - for (i = 0; i < 20; i++) - solo_reg_write(dev, SOLO_VO_CURSOR_MASK(i), 0); - - solo_reg_write(dev, SOLO_VO_CURSOR_POS, 0); - - solo_reg_write(dev, SOLO_VO_CURSOR_CLR, - (0x80 << 24) | (0x80 << 16) | (0x10 << 8) | 0x80); - solo_reg_write(dev, SOLO_VO_CURSOR_CLR2, (0xe0 << 8) | 0x80); -} - -static void solo_vout_config(struct solo_dev *solo_dev) -{ - solo_dev->vout_hstart = 6; - solo_dev->vout_vstart = 8; - - solo_reg_write(solo_dev, SOLO_VO_FMT_ENC, - solo_dev->video_type | - SOLO_VO_USER_COLOR_SET_NAV | - SOLO_VO_USER_COLOR_SET_NAH | - SOLO_VO_NA_COLOR_Y(0) | - SOLO_VO_NA_COLOR_CB(0) | - SOLO_VO_NA_COLOR_CR(0)); - - solo_reg_write(solo_dev, SOLO_VO_ACT_H, - SOLO_VO_H_START(solo_dev->vout_hstart) | - SOLO_VO_H_STOP(solo_dev->vout_hstart + - solo_dev->video_hsize)); - - solo_reg_write(solo_dev, SOLO_VO_ACT_V, - SOLO_VO_V_START(solo_dev->vout_vstart) | - SOLO_VO_V_STOP(solo_dev->vout_vstart + - solo_dev->video_vsize)); - - solo_reg_write(solo_dev, SOLO_VO_RANGE_HV, - SOLO_VO_H_LEN(solo_dev->video_hsize) | - SOLO_VO_V_LEN(solo_dev->video_vsize)); - - /* Border & background colors */ - solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_COLOR, - (0xa0 << 24) | (0x88 << 16) | (0xa0 << 8) | 0x88); - solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_COLOR, - (0x10 << 24) | (0x8f << 16) | (0x10 << 8) | 0x8f); - solo_reg_write(solo_dev, SOLO_VO_BKG_COLOR, - (16 << 24) | (128 << 16) | (16 << 8) | 128); - - solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON); - - solo_reg_write(solo_dev, SOLO_VI_WIN_SW, 0); - - solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0); - solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0); - - solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, SOLO_VO_DISP_ON | - SOLO_VO_DISP_ERASE_COUNT(8) | - SOLO_VO_DISP_BASE(SOLO_DISP_EXT_ADDR)); - - - solo_vout_config_cursor(solo_dev); - - /* Enable channels we support */ - solo_reg_write(solo_dev, SOLO_VI_CH_ENA, - (1 << solo_dev->nr_chans) - 1); -} - -static int solo_dma_vin_region(struct solo_dev *solo_dev, u32 off, - u16 val, int reg_size) -{ - u16 *buf; - const int n = 64, size = n * sizeof(*buf); - int i, ret = 0; - - buf = kmalloc(size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - for (i = 0; i < n; i++) - buf[i] = cpu_to_le16(val); - - for (i = 0; i < reg_size; i += size) { - ret = solo_p2m_dma(solo_dev, 1, buf, - SOLO_MOTION_EXT_ADDR(solo_dev) + off + i, - size, 0, 0); - - if (ret) - break; - } - - kfree(buf); - return ret; -} - -int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val) -{ - if (ch > solo_dev->nr_chans) - return -EINVAL; - - return solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA + - (ch * SOLO_MOT_THRESH_SIZE * 2), - val, SOLO_MOT_THRESH_SIZE); -} - -int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch, - const struct solo_motion_thresholds *thresholds) -{ - u32 off = SOLO_MOT_FLAG_AREA + ch * SOLO_MOT_THRESH_SIZE * 2; - u16 buf[64]; - int x, y; - int ret = 0; - - memset(buf, 0, sizeof(buf)); - for (y = 0; y < SOLO_MOTION_SZ; y++) { - for (x = 0; x < SOLO_MOTION_SZ; x++) - buf[x] = cpu_to_le16(thresholds->thresholds[y][x]); - ret |= solo_p2m_dma(solo_dev, 1, buf, - SOLO_MOTION_EXT_ADDR(solo_dev) + off + y * sizeof(buf), - sizeof(buf), 0, 0); - } - return ret; -} - -/* First 8k is motion flag (512 bytes * 16). Following that is an 8k+8k - * threshold and working table for each channel. Atleast that's what the - * spec says. However, this code (taken from rdk) has some mystery 8k - * block right after the flag area, before the first thresh table. */ -static void solo_motion_config(struct solo_dev *solo_dev) -{ - int i; - - for (i = 0; i < solo_dev->nr_chans; i++) { - /* Clear motion flag area */ - solo_dma_vin_region(solo_dev, i * SOLO_MOT_FLAG_SIZE, 0x0000, - SOLO_MOT_FLAG_SIZE); - - /* Clear working cache table */ - solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA + - (i * SOLO_MOT_THRESH_SIZE * 2) + - SOLO_MOT_THRESH_SIZE, 0x0000, - SOLO_MOT_THRESH_SIZE); - - /* Set default threshold table */ - solo_set_motion_threshold(solo_dev, i, SOLO_DEF_MOT_THRESH); - } - - /* Default motion settings */ - solo_reg_write(solo_dev, SOLO_VI_MOT_ADR, SOLO_VI_MOTION_EN(0) | - (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16)); - solo_reg_write(solo_dev, SOLO_VI_MOT_CTRL, - SOLO_VI_MOTION_FRAME_COUNT(3) | - SOLO_VI_MOTION_SAMPLE_LENGTH(solo_dev->video_hsize / 16) - /* | SOLO_VI_MOTION_INTR_START_STOP */ - | SOLO_VI_MOTION_SAMPLE_COUNT(10)); - - solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0); - solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0); -} - -int solo_disp_init(struct solo_dev *solo_dev) -{ - int i; - - solo_dev->video_hsize = 704; - if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) { - solo_dev->video_vsize = 240; - solo_dev->fps = 30; - } else { - solo_dev->video_vsize = 288; - solo_dev->fps = 25; - } - - solo_vin_config(solo_dev); - solo_motion_config(solo_dev); - solo_vout_config(solo_dev); - - for (i = 0; i < solo_dev->nr_chans; i++) - solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 1); - - return 0; -} - -void solo_disp_exit(struct solo_dev *solo_dev) -{ - int i; - - solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, 0); - solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0); - solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0); - - for (i = 0; i < solo_dev->nr_chans; i++) { - solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(i), 0); - solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(i), 0); - solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 0); - } - - /* Set default border */ - for (i = 0; i < 5; i++) - solo_reg_write(solo_dev, SOLO_VO_BORDER_X(i), 0); - - for (i = 0; i < 5; i++) - solo_reg_write(solo_dev, SOLO_VO_BORDER_Y(i), 0); - - solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_MASK, 0); - solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_MASK, 0); - - solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(0), 0); - solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(0), 0); - solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(0), 0); - - solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_CTRL(1), 0); - solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_START(1), 0); - solo_reg_write(solo_dev, SOLO_VO_RECTANGLE_STOP(1), 0); -} diff --git a/drivers/staging/media/solo6x10/solo6x10-eeprom.c b/drivers/staging/media/solo6x10/solo6x10-eeprom.c deleted file mode 100644 index 9d1c9bb53d6b..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-eeprom.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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/kernel.h> -#include <linux/delay.h> - -#include "solo6x10.h" - -/* Control */ -#define EE_SHIFT_CLK 0x04 -#define EE_CS 0x08 -#define EE_DATA_WRITE 0x02 -#define EE_DATA_READ 0x01 -#define EE_ENB (0x80 | EE_CS) - -#define eeprom_delay() udelay(100) -#if 0 -#define eeprom_delay() solo_reg_read(solo_dev, SOLO_EEPROM_CTRL) -#define eeprom_delay() ({ \ - int i, ret; \ - udelay(100); \ - for (i = ret = 0; i < 1000 && !ret; i++) \ - ret = solo_eeprom_reg_read(solo_dev); \ -}) -#endif -#define ADDR_LEN 6 - -/* Commands */ -#define EE_EWEN_CMD 4 -#define EE_EWDS_CMD 4 -#define EE_WRITE_CMD 5 -#define EE_READ_CMD 6 -#define EE_ERASE_CMD 7 - -static unsigned int solo_eeprom_reg_read(struct solo_dev *solo_dev) -{ - return solo_reg_read(solo_dev, SOLO_EEPROM_CTRL) & EE_DATA_READ; -} - -static void solo_eeprom_reg_write(struct solo_dev *solo_dev, u32 data) -{ - solo_reg_write(solo_dev, SOLO_EEPROM_CTRL, data); - eeprom_delay(); -} - -static void solo_eeprom_cmd(struct solo_dev *solo_dev, int cmd) -{ - int i; - - solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ACCESS_EN); - solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE); - - for (i = 4 + ADDR_LEN; i >= 0; i--) { - int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0; - - solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE | dataval); - solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE | - EE_SHIFT_CLK | dataval); - } - - solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE); -} - -unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en) -{ - int ewen_cmd = (w_en ? 0x3f : 0) | (EE_EWEN_CMD << ADDR_LEN); - unsigned int retval = 0; - int i; - - solo_eeprom_cmd(solo_dev, ewen_cmd); - - for (i = 0; i < 16; i++) { - solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE | - EE_SHIFT_CLK); - retval = (retval << 1) | solo_eeprom_reg_read(solo_dev); - solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE); - retval = (retval << 1) | solo_eeprom_reg_read(solo_dev); - } - - solo_eeprom_reg_write(solo_dev, ~EE_CS); - retval = (retval << 1) | solo_eeprom_reg_read(solo_dev); - - return retval; -} - -unsigned short solo_eeprom_read(struct solo_dev *solo_dev, int loc) -{ - int read_cmd = loc | (EE_READ_CMD << ADDR_LEN); - unsigned short retval = 0; - int i; - - solo_eeprom_cmd(solo_dev, read_cmd); - - for (i = 0; i < 16; i++) { - solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE | - EE_SHIFT_CLK); - retval = (retval << 1) | solo_eeprom_reg_read(solo_dev); - solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE); - } - - solo_eeprom_reg_write(solo_dev, ~EE_CS); - - return retval; -} - -int solo_eeprom_write(struct solo_dev *solo_dev, int loc, - unsigned short data) -{ - int write_cmd = loc | (EE_WRITE_CMD << ADDR_LEN); - unsigned int retval; - int i; - - solo_eeprom_cmd(solo_dev, write_cmd); - - for (i = 15; i >= 0; i--) { - unsigned int dataval = (data >> i) & 1; - - solo_eeprom_reg_write(solo_dev, EE_ENB); - solo_eeprom_reg_write(solo_dev, - EE_ENB | (dataval << 1) | EE_SHIFT_CLK); - } - - solo_eeprom_reg_write(solo_dev, EE_ENB); - solo_eeprom_reg_write(solo_dev, ~EE_CS); - solo_eeprom_reg_write(solo_dev, EE_ENB); - - for (i = retval = 0; i < 10000 && !retval; i++) - retval = solo_eeprom_reg_read(solo_dev); - - solo_eeprom_reg_write(solo_dev, ~EE_CS); - - return !retval; -} diff --git a/drivers/staging/media/solo6x10/solo6x10-enc.c b/drivers/staging/media/solo6x10/solo6x10-enc.c deleted file mode 100644 index 2db53b68c62f..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-enc.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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/kernel.h> -#include <linux/font.h> -#include <linux/bitrev.h> -#include <linux/slab.h> - -#include "solo6x10.h" - -#define VI_PROG_HSIZE (1280 - 16) -#define VI_PROG_VSIZE (1024 - 16) - -#define IRQ_LEVEL 2 - -static void solo_capture_config(struct solo_dev *solo_dev) -{ - unsigned long height; - unsigned long width; - void *buf; - int i; - - solo_reg_write(solo_dev, SOLO_CAP_BASE, - SOLO_CAP_MAX_PAGE((SOLO_CAP_EXT_SIZE(solo_dev) - - SOLO_CAP_PAGE_SIZE) >> 16) - | SOLO_CAP_BASE_ADDR(SOLO_CAP_EXT_ADDR(solo_dev) >> 16)); - - /* XXX: Undocumented bits at b17 and b24 */ - if (solo_dev->type == SOLO_DEV_6110) { - /* NOTE: Ref driver has (62 << 24) here as well, but it causes - * wacked out frame timing on 4-port 6110. */ - solo_reg_write(solo_dev, SOLO_CAP_BTW, - (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) | - SOLO_CAP_MAX_BANDWIDTH(36)); - } else { - solo_reg_write(solo_dev, SOLO_CAP_BTW, - (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) | - SOLO_CAP_MAX_BANDWIDTH(32)); - } - - /* Set scale 1, 9 dimension */ - width = solo_dev->video_hsize; - height = solo_dev->video_vsize; - solo_reg_write(solo_dev, SOLO_DIM_SCALE1, - SOLO_DIM_H_MB_NUM(width / 16) | - SOLO_DIM_V_MB_NUM_FRAME(height / 8) | - SOLO_DIM_V_MB_NUM_FIELD(height / 16)); - - /* Set scale 2, 10 dimension */ - width = solo_dev->video_hsize / 2; - height = solo_dev->video_vsize; - solo_reg_write(solo_dev, SOLO_DIM_SCALE2, - SOLO_DIM_H_MB_NUM(width / 16) | - SOLO_DIM_V_MB_NUM_FRAME(height / 8) | - SOLO_DIM_V_MB_NUM_FIELD(height / 16)); - - /* Set scale 3, 11 dimension */ - width = solo_dev->video_hsize / 2; - height = solo_dev->video_vsize / 2; - solo_reg_write(solo_dev, SOLO_DIM_SCALE3, - SOLO_DIM_H_MB_NUM(width / 16) | - SOLO_DIM_V_MB_NUM_FRAME(height / 8) | - SOLO_DIM_V_MB_NUM_FIELD(height / 16)); - - /* Set scale 4, 12 dimension */ - width = solo_dev->video_hsize / 3; - height = solo_dev->video_vsize / 3; - solo_reg_write(solo_dev, SOLO_DIM_SCALE4, - SOLO_DIM_H_MB_NUM(width / 16) | - SOLO_DIM_V_MB_NUM_FRAME(height / 8) | - SOLO_DIM_V_MB_NUM_FIELD(height / 16)); - - /* Set scale 5, 13 dimension */ - width = solo_dev->video_hsize / 4; - height = solo_dev->video_vsize / 2; - solo_reg_write(solo_dev, SOLO_DIM_SCALE5, - SOLO_DIM_H_MB_NUM(width / 16) | - SOLO_DIM_V_MB_NUM_FRAME(height / 8) | - SOLO_DIM_V_MB_NUM_FIELD(height / 16)); - - /* Progressive */ - width = VI_PROG_HSIZE; - height = VI_PROG_VSIZE; - solo_reg_write(solo_dev, SOLO_DIM_PROG, - SOLO_DIM_H_MB_NUM(width / 16) | - SOLO_DIM_V_MB_NUM_FRAME(height / 16) | - SOLO_DIM_V_MB_NUM_FIELD(height / 16)); - - /* Clear OSD */ - solo_reg_write(solo_dev, SOLO_VE_OSD_CH, 0); - solo_reg_write(solo_dev, SOLO_VE_OSD_BASE, SOLO_EOSD_EXT_ADDR >> 16); - solo_reg_write(solo_dev, SOLO_VE_OSD_CLR, - 0xF0 << 16 | 0x80 << 8 | 0x80); - - if (solo_dev->type == SOLO_DEV_6010) - solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, - SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW); - else - solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, SOLO_VE_OSD_V_DOUBLE - | SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW); - - /* Clear OSG buffer */ - buf = kzalloc(SOLO_EOSD_EXT_SIZE(solo_dev), GFP_KERNEL); - if (!buf) - return; - - for (i = 0; i < solo_dev->nr_chans; i++) { - solo_p2m_dma(solo_dev, 1, buf, - SOLO_EOSD_EXT_ADDR + - (SOLO_EOSD_EXT_SIZE(solo_dev) * i), - SOLO_EOSD_EXT_SIZE(solo_dev), 0, 0); - } - kfree(buf); -} - -#define SOLO_OSD_WRITE_SIZE (16 * OSD_TEXT_MAX) - -/* Should be called with enable_lock held */ -int solo_osd_print(struct solo_enc_dev *solo_enc) -{ - struct solo_dev *solo_dev = solo_enc->solo_dev; - unsigned char *str = solo_enc->osd_text; - u8 *buf = solo_enc->osd_buf; - u32 reg; - const struct font_desc *vga = find_font("VGA8x16"); - const unsigned char *vga_data; - int i, j; - - if (WARN_ON_ONCE(!vga)) - return -ENODEV; - - reg = solo_reg_read(solo_dev, SOLO_VE_OSD_CH); - if (!*str) { - /* Disable OSD on this channel */ - reg &= ~(1 << solo_enc->ch); - goto out; - } - - memset(buf, 0, SOLO_OSD_WRITE_SIZE); - vga_data = (const unsigned char *)vga->data; - - for (i = 0; *str; i++, str++) { - for (j = 0; j < 16; j++) { - buf[(j << 1) | (i & 1) | ((i & ~1) << 4)] = - bitrev8(vga_data[(*str << 4) | j]); - } - } - - solo_p2m_dma(solo_dev, 1, buf, - SOLO_EOSD_EXT_ADDR_CHAN(solo_dev, solo_enc->ch), - SOLO_OSD_WRITE_SIZE, 0, 0); - - /* Enable OSD on this channel */ - reg |= (1 << solo_enc->ch); - -out: - solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg); - return 0; -} - -/** - * Set channel Quality Profile (0-3). - */ -void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch, - unsigned int qp) -{ - unsigned long flags; - unsigned int idx, reg; - - if ((ch > 31) || (qp > 3)) - return; - - if (solo_dev->type == SOLO_DEV_6010) - return; - - if (ch < 16) { - idx = 0; - reg = SOLO_VE_JPEG_QP_CH_L; - } else { - ch -= 16; - idx = 1; - reg = SOLO_VE_JPEG_QP_CH_H; - } - ch *= 2; - - spin_lock_irqsave(&solo_dev->jpeg_qp_lock, flags); - - solo_dev->jpeg_qp[idx] &= ~(3 << ch); - solo_dev->jpeg_qp[idx] |= (qp & 3) << ch; - - solo_reg_write(solo_dev, reg, solo_dev->jpeg_qp[idx]); - - spin_unlock_irqrestore(&solo_dev->jpeg_qp_lock, flags); -} - -int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch) -{ - int idx; - - if (solo_dev->type == SOLO_DEV_6010) - return 2; - - if (WARN_ON_ONCE(ch > 31)) - return 2; - - if (ch < 16) { - idx = 0; - } else { - ch -= 16; - idx = 1; - } - ch *= 2; - - return (solo_dev->jpeg_qp[idx] >> ch) & 3; -} - -#define SOLO_QP_INIT 0xaaaaaaaa - -static void solo_jpeg_config(struct solo_dev *solo_dev) -{ - if (solo_dev->type == SOLO_DEV_6010) { - solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL, - (2 << 24) | (2 << 16) | (2 << 8) | 2); - } else { - solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL, - (4 << 24) | (3 << 16) | (2 << 8) | 1); - } - - spin_lock_init(&solo_dev->jpeg_qp_lock); - - /* Initialize Quality Profile for all channels */ - solo_dev->jpeg_qp[0] = solo_dev->jpeg_qp[1] = SOLO_QP_INIT; - solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_L, SOLO_QP_INIT); - solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_H, SOLO_QP_INIT); - - solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG, - (SOLO_JPEG_EXT_SIZE(solo_dev) & 0xffff0000) | - ((SOLO_JPEG_EXT_ADDR(solo_dev) >> 16) & 0x0000ffff)); - solo_reg_write(solo_dev, SOLO_VE_JPEG_CTRL, 0xffffffff); - if (solo_dev->type == SOLO_DEV_6110) { - solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG1, - (0 << 16) | (30 << 8) | 60); - } -} - -static void solo_mp4e_config(struct solo_dev *solo_dev) -{ - int i; - u32 cfg; - - solo_reg_write(solo_dev, SOLO_VE_CFG0, - SOLO_VE_INTR_CTRL(IRQ_LEVEL) | - SOLO_VE_BLOCK_SIZE(SOLO_MP4E_EXT_SIZE(solo_dev) >> 16) | - SOLO_VE_BLOCK_BASE(SOLO_MP4E_EXT_ADDR(solo_dev) >> 16)); - - - cfg = SOLO_VE_BYTE_ALIGN(2) | SOLO_VE_INSERT_INDEX - | SOLO_VE_MOTION_MODE(0); - if (solo_dev->type != SOLO_DEV_6010) { - cfg |= SOLO_VE_MPEG_SIZE_H( - (SOLO_MP4E_EXT_SIZE(solo_dev) >> 24) & 0x0f); - cfg |= SOLO_VE_JPEG_SIZE_H( - (SOLO_JPEG_EXT_SIZE(solo_dev) >> 24) & 0x0f); - } - solo_reg_write(solo_dev, SOLO_VE_CFG1, cfg); - - solo_reg_write(solo_dev, SOLO_VE_WMRK_POLY, 0); - solo_reg_write(solo_dev, SOLO_VE_VMRK_INIT_KEY, 0); - solo_reg_write(solo_dev, SOLO_VE_WMRK_STRL, 0); - if (solo_dev->type == SOLO_DEV_6110) - solo_reg_write(solo_dev, SOLO_VE_WMRK_ENABLE, 0); - solo_reg_write(solo_dev, SOLO_VE_ENCRYP_POLY, 0); - solo_reg_write(solo_dev, SOLO_VE_ENCRYP_INIT, 0); - - solo_reg_write(solo_dev, SOLO_VE_ATTR, - SOLO_VE_LITTLE_ENDIAN | - SOLO_COMP_ATTR_FCODE(1) | - SOLO_COMP_TIME_INC(0) | - SOLO_COMP_TIME_WIDTH(15) | - SOLO_DCT_INTERVAL(solo_dev->type == SOLO_DEV_6010 ? 9 : 10)); - - for (i = 0; i < solo_dev->nr_chans; i++) { - solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE(i), - (SOLO_EREF_EXT_ADDR(solo_dev) + - (i * SOLO_EREF_EXT_SIZE)) >> 16); - solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE_E(i), - (SOLO_EREF_EXT_ADDR(solo_dev) + - ((i + 16) * SOLO_EREF_EXT_SIZE)) >> 16); - } - - if (solo_dev->type == SOLO_DEV_6110) { - solo_reg_write(solo_dev, SOLO_VE_COMPT_MOT, 0x00040008); - } else { - for (i = 0; i < solo_dev->nr_chans; i++) - solo_reg_write(solo_dev, SOLO_VE_CH_MOT(i), 0x100); - } -} - -int solo_enc_init(struct solo_dev *solo_dev) -{ - int i; - - solo_capture_config(solo_dev); - solo_mp4e_config(solo_dev); - solo_jpeg_config(solo_dev); - - for (i = 0; i < solo_dev->nr_chans; i++) { - solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0); - solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0); - } - - return 0; -} - -void solo_enc_exit(struct solo_dev *solo_dev) -{ - int i; - - for (i = 0; i < solo_dev->nr_chans; i++) { - solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0); - solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0); - } -} diff --git a/drivers/staging/media/solo6x10/solo6x10-g723.c b/drivers/staging/media/solo6x10/solo6x10-g723.c deleted file mode 100644 index 74f037b6166c..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-g723.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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/kernel.h> -#include <linux/mempool.h> -#include <linux/poll.h> -#include <linux/kthread.h> -#include <linux/freezer.h> -#include <linux/module.h> -#include <linux/slab.h> - -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/pcm.h> -#include <sound/control.h> - -#include "solo6x10.h" -#include "solo6x10-tw28.h" - -#define G723_FDMA_PAGES 32 -#define G723_PERIOD_BYTES 48 -#define G723_PERIOD_BLOCK 1024 -#define G723_FRAMES_PER_PAGE 48 - -/* Sets up channels 16-19 for decoding and 0-15 for encoding */ -#define OUTMODE_MASK 0x300 - -#define SAMPLERATE 8000 -#define BITRATE 25 - -/* The solo writes to 1k byte pages, 32 pages, in the dma. Each 1k page - * is broken down to 20 * 48 byte regions (one for each channel possible) - * with the rest of the page being dummy data. */ -#define G723_MAX_BUFFER (G723_PERIOD_BYTES * PERIODS_MAX) -#define G723_INTR_ORDER 4 /* 0 - 4 */ -#define PERIODS_MIN (1 << G723_INTR_ORDER) -#define PERIODS_MAX G723_FDMA_PAGES - -struct solo_snd_pcm { - int on; - spinlock_t lock; - struct solo_dev *solo_dev; - unsigned char *g723_buf; - dma_addr_t g723_dma; -}; - -static void solo_g723_config(struct solo_dev *solo_dev) -{ - int clk_div; - - clk_div = (solo_dev->clock_mhz * 1000000) - / (SAMPLERATE * (BITRATE * 2) * 2); - - solo_reg_write(solo_dev, SOLO_AUDIO_SAMPLE, - SOLO_AUDIO_BITRATE(BITRATE) - | SOLO_AUDIO_CLK_DIV(clk_div)); - - solo_reg_write(solo_dev, SOLO_AUDIO_FDMA_INTR, - SOLO_AUDIO_FDMA_INTERVAL(1) - | SOLO_AUDIO_INTR_ORDER(G723_INTR_ORDER) - | SOLO_AUDIO_FDMA_BASE(SOLO_G723_EXT_ADDR(solo_dev) >> 16)); - - solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL, - SOLO_AUDIO_ENABLE - | SOLO_AUDIO_I2S_MODE - | SOLO_AUDIO_I2S_MULTI(3) - | SOLO_AUDIO_MODE(OUTMODE_MASK)); -} - -void solo_g723_isr(struct solo_dev *solo_dev) -{ - struct snd_pcm_str *pstr = - &solo_dev->snd_pcm->streams[SNDRV_PCM_STREAM_CAPTURE]; - struct snd_pcm_substream *ss; - struct solo_snd_pcm *solo_pcm; - - for (ss = pstr->substream; ss != NULL; ss = ss->next) { - if (snd_pcm_substream_chip(ss) == NULL) - continue; - - /* This means open() hasn't been called on this one */ - if (snd_pcm_substream_chip(ss) == solo_dev) - continue; - - /* Haven't triggered a start yet */ - solo_pcm = snd_pcm_substream_chip(ss); - if (!solo_pcm->on) - continue; - - snd_pcm_period_elapsed(ss); - } -} - -static int snd_solo_hw_params(struct snd_pcm_substream *ss, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw_params)); -} - -static int snd_solo_hw_free(struct snd_pcm_substream *ss) -{ - return snd_pcm_lib_free_pages(ss); -} - -static const struct snd_pcm_hardware snd_solo_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8, - .rates = SNDRV_PCM_RATE_8000, - .rate_min = SAMPLERATE, - .rate_max = SAMPLERATE, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = G723_MAX_BUFFER, - .period_bytes_min = G723_PERIOD_BYTES, - .period_bytes_max = G723_PERIOD_BYTES, - .periods_min = PERIODS_MIN, - .periods_max = PERIODS_MAX, -}; - -static int snd_solo_pcm_open(struct snd_pcm_substream *ss) -{ - struct solo_dev *solo_dev = snd_pcm_substream_chip(ss); - struct solo_snd_pcm *solo_pcm; - - solo_pcm = kzalloc(sizeof(*solo_pcm), GFP_KERNEL); - if (solo_pcm == NULL) - goto oom; - - solo_pcm->g723_buf = pci_alloc_consistent(solo_dev->pdev, - G723_PERIOD_BYTES, - &solo_pcm->g723_dma); - if (solo_pcm->g723_buf == NULL) - goto oom; - - spin_lock_init(&solo_pcm->lock); - solo_pcm->solo_dev = solo_dev; - ss->runtime->hw = snd_solo_pcm_hw; - - snd_pcm_substream_chip(ss) = solo_pcm; - - return 0; - -oom: - kfree(solo_pcm); - return -ENOMEM; -} - -static int snd_solo_pcm_close(struct snd_pcm_substream *ss) -{ - struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); - - snd_pcm_substream_chip(ss) = solo_pcm->solo_dev; - pci_free_consistent(solo_pcm->solo_dev->pdev, G723_PERIOD_BYTES, - solo_pcm->g723_buf, solo_pcm->g723_dma); - kfree(solo_pcm); - - return 0; -} - -static int snd_solo_pcm_trigger(struct snd_pcm_substream *ss, int cmd) -{ - struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); - struct solo_dev *solo_dev = solo_pcm->solo_dev; - int ret = 0; - - spin_lock(&solo_pcm->lock); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if (solo_pcm->on == 0) { - /* If this is the first user, switch on interrupts */ - if (atomic_inc_return(&solo_dev->snd_users) == 1) - solo_irq_on(solo_dev, SOLO_IRQ_G723); - solo_pcm->on = 1; - } - break; - case SNDRV_PCM_TRIGGER_STOP: - if (solo_pcm->on) { - /* If this was our last user, switch them off */ - if (atomic_dec_return(&solo_dev->snd_users) == 0) - solo_irq_off(solo_dev, SOLO_IRQ_G723); - solo_pcm->on = 0; - } - break; - default: - ret = -EINVAL; - } - - spin_unlock(&solo_pcm->lock); - - return ret; -} - -static int snd_solo_pcm_prepare(struct snd_pcm_substream *ss) -{ - return 0; -} - -static snd_pcm_uframes_t snd_solo_pcm_pointer(struct snd_pcm_substream *ss) -{ - struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); - struct solo_dev *solo_dev = solo_pcm->solo_dev; - snd_pcm_uframes_t idx = solo_reg_read(solo_dev, SOLO_AUDIO_STA) & 0x1f; - - return idx * G723_FRAMES_PER_PAGE; -} - -static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel, - snd_pcm_uframes_t pos, void __user *dst, - snd_pcm_uframes_t count) -{ - struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); - struct solo_dev *solo_dev = solo_pcm->solo_dev; - int err, i; - - for (i = 0; i < (count / G723_FRAMES_PER_PAGE); i++) { - int page = (pos / G723_FRAMES_PER_PAGE) + i; - - err = solo_p2m_dma_t(solo_dev, 0, solo_pcm->g723_dma, - SOLO_G723_EXT_ADDR(solo_dev) + - (page * G723_PERIOD_BLOCK) + - (ss->number * G723_PERIOD_BYTES), - G723_PERIOD_BYTES, 0, 0); - if (err) - return err; - - err = copy_to_user(dst + (i * G723_PERIOD_BYTES), - solo_pcm->g723_buf, G723_PERIOD_BYTES); - - if (err) - return -EFAULT; - } - - return 0; -} - -static struct snd_pcm_ops snd_solo_pcm_ops = { - .open = snd_solo_pcm_open, - .close = snd_solo_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_solo_hw_params, - .hw_free = snd_solo_hw_free, - .prepare = snd_solo_pcm_prepare, - .trigger = snd_solo_pcm_trigger, - .pointer = snd_solo_pcm_pointer, - .copy = snd_solo_pcm_copy, -}; - -static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 1; - info->value.integer.min = 0; - info->value.integer.max = 15; - info->value.integer.step = 1; - - return 0; -} - -static int snd_solo_capture_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol); - u8 ch = value->id.numid - 1; - - value->value.integer.value[0] = tw28_get_audio_gain(solo_dev, ch); - - return 0; -} - -static int snd_solo_capture_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol); - u8 ch = value->id.numid - 1; - u8 old_val; - - old_val = tw28_get_audio_gain(solo_dev, ch); - if (old_val == value->value.integer.value[0]) - return 0; - - tw28_set_audio_gain(solo_dev, ch, value->value.integer.value[0]); - - return 1; -} - -static struct snd_kcontrol_new snd_solo_capture_volume = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Volume", - .info = snd_solo_capture_volume_info, - .get = snd_solo_capture_volume_get, - .put = snd_solo_capture_volume_put, -}; - -static int solo_snd_pcm_init(struct solo_dev *solo_dev) -{ - struct snd_card *card = solo_dev->snd_card; - struct snd_pcm *pcm; - struct snd_pcm_substream *ss; - int ret; - int i; - - ret = snd_pcm_new(card, card->driver, 0, 0, solo_dev->nr_chans, - &pcm); - if (ret < 0) - return ret; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_solo_pcm_ops); - - snd_pcm_chip(pcm) = solo_dev; - pcm->info_flags = 0; - strcpy(pcm->name, card->shortname); - - for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - ss; ss = ss->next, i++) - sprintf(ss->name, "Camera #%d Audio", i); - - ret = snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - G723_MAX_BUFFER, G723_MAX_BUFFER); - if (ret < 0) - return ret; - - solo_dev->snd_pcm = pcm; - - return 0; -} - -int solo_g723_init(struct solo_dev *solo_dev) -{ - static struct snd_device_ops ops = { NULL }; - struct snd_card *card; - struct snd_kcontrol_new kctl; - char name[32]; - int ret; - - atomic_set(&solo_dev->snd_users, 0); - - /* Allows for easier mapping between video and audio */ - sprintf(name, "Softlogic%d", solo_dev->vfd->num); - - ret = snd_card_new(&solo_dev->pdev->dev, - SNDRV_DEFAULT_IDX1, name, THIS_MODULE, 0, - &solo_dev->snd_card); - if (ret < 0) - return ret; - - card = solo_dev->snd_card; - - strcpy(card->driver, SOLO6X10_NAME); - strcpy(card->shortname, "SOLO-6x10 Audio"); - sprintf(card->longname, "%s on %s IRQ %d", card->shortname, - pci_name(solo_dev->pdev), solo_dev->pdev->irq); - - ret = snd_device_new(card, SNDRV_DEV_LOWLEVEL, solo_dev, &ops); - if (ret < 0) - goto snd_error; - - /* Mixer controls */ - strcpy(card->mixername, "SOLO-6x10"); - kctl = snd_solo_capture_volume; - kctl.count = solo_dev->nr_chans; - - ret = snd_ctl_add(card, snd_ctl_new1(&kctl, solo_dev)); - if (ret < 0) - return ret; - - ret = solo_snd_pcm_init(solo_dev); - if (ret < 0) - goto snd_error; - - ret = snd_card_register(card); - if (ret < 0) - goto snd_error; - - solo_g723_config(solo_dev); - - dev_info(&solo_dev->pdev->dev, "Alsa sound card as %s\n", name); - - return 0; - -snd_error: - snd_card_free(card); - return ret; -} - -void solo_g723_exit(struct solo_dev *solo_dev) -{ - if (!solo_dev->snd_card) - return; - - solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL, 0); - solo_irq_off(solo_dev, SOLO_IRQ_G723); - - snd_card_free(solo_dev->snd_card); - solo_dev->snd_card = NULL; -} diff --git a/drivers/staging/media/solo6x10/solo6x10-gpio.c b/drivers/staging/media/solo6x10/solo6x10-gpio.c deleted file mode 100644 index 73276dc92875..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-gpio.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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/kernel.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/uaccess.h> - -#include "solo6x10.h" - -static void solo_gpio_mode(struct solo_dev *solo_dev, - unsigned int port_mask, unsigned int mode) -{ - int port; - unsigned int ret; - - ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_0); - - /* To set gpio */ - for (port = 0; port < 16; port++) { - if (!((1 << port) & port_mask)) - continue; - - ret &= (~(3 << (port << 1))); - ret |= ((mode & 3) << (port << 1)); - } - - solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_0, ret); - - /* To set extended gpio - sensor */ - ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_1); - - for (port = 0; port < 16; port++) { - if (!((1 << (port + 16)) & port_mask)) - continue; - - if (!mode) - ret &= ~(1 << port); - else - ret |= 1 << port; - } - - solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_1, ret); -} - -static void solo_gpio_set(struct solo_dev *solo_dev, unsigned int value) -{ - solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT, - solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) | value); -} - -static void solo_gpio_clear(struct solo_dev *solo_dev, unsigned int value) -{ - solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT, - solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) & ~value); -} - -static void solo_gpio_config(struct solo_dev *solo_dev) -{ - /* Video reset */ - solo_gpio_mode(solo_dev, 0x30, 1); - solo_gpio_clear(solo_dev, 0x30); - udelay(100); - solo_gpio_set(solo_dev, 0x30); - udelay(100); - - /* Warning: Don't touch the next line unless you're sure of what - * you're doing: first four gpio [0-3] are used for video. */ - solo_gpio_mode(solo_dev, 0x0f, 2); - - /* We use bit 8-15 of SOLO_GPIO_CONFIG_0 for relay purposes */ - solo_gpio_mode(solo_dev, 0xff00, 1); - - /* Initially set relay status to 0 */ - solo_gpio_clear(solo_dev, 0xff00); -} - -int solo_gpio_init(struct solo_dev *solo_dev) -{ - solo_gpio_config(solo_dev); - return 0; -} - -void solo_gpio_exit(struct solo_dev *solo_dev) -{ - solo_gpio_clear(solo_dev, 0x30); - solo_gpio_config(solo_dev); -} diff --git a/drivers/staging/media/solo6x10/solo6x10-i2c.c b/drivers/staging/media/solo6x10/solo6x10-i2c.c deleted file mode 100644 index 01aa417c9258..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-i2c.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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. - */ - -/* XXX: The SOLO6x10 i2c does not have separate interrupts for each i2c - * channel. The bus can only handle one i2c event at a time. The below handles - * this all wrong. We should be using the status registers to see if the bus - * is in use, and have a global lock to check the status register. Also, - * the bulk of the work should be handled out-of-interrupt. The ugly loops - * that occur during interrupt scare me. The ISR should merely signal - * thread context, ACK the interrupt, and move on. -- BenC */ - -#include <linux/kernel.h> - -#include "solo6x10.h" - -u8 solo_i2c_readbyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off) -{ - struct i2c_msg msgs[2]; - u8 data; - - msgs[0].flags = 0; - msgs[0].addr = addr; - msgs[0].len = 1; - msgs[0].buf = &off; - - msgs[1].flags = I2C_M_RD; - msgs[1].addr = addr; - msgs[1].len = 1; - msgs[1].buf = &data; - - i2c_transfer(&solo_dev->i2c_adap[id], msgs, 2); - - return data; -} - -void solo_i2c_writebyte(struct solo_dev *solo_dev, int id, u8 addr, - u8 off, u8 data) -{ - struct i2c_msg msgs; - u8 buf[2]; - - buf[0] = off; - buf[1] = data; - msgs.flags = 0; - msgs.addr = addr; - msgs.len = 2; - msgs.buf = buf; - - i2c_transfer(&solo_dev->i2c_adap[id], &msgs, 1); -} - -static void solo_i2c_flush(struct solo_dev *solo_dev, int wr) -{ - u32 ctrl; - - ctrl = SOLO_IIC_CH_SET(solo_dev->i2c_id); - - if (solo_dev->i2c_state == IIC_STATE_START) - ctrl |= SOLO_IIC_START; - - if (wr) { - ctrl |= SOLO_IIC_WRITE; - } else { - ctrl |= SOLO_IIC_READ; - if (!(solo_dev->i2c_msg->flags & I2C_M_NO_RD_ACK)) - ctrl |= SOLO_IIC_ACK_EN; - } - - if (solo_dev->i2c_msg_ptr == solo_dev->i2c_msg->len) - ctrl |= SOLO_IIC_STOP; - - solo_reg_write(solo_dev, SOLO_IIC_CTRL, ctrl); -} - -static void solo_i2c_start(struct solo_dev *solo_dev) -{ - u32 addr = solo_dev->i2c_msg->addr << 1; - - if (solo_dev->i2c_msg->flags & I2C_M_RD) - addr |= 1; - - solo_dev->i2c_state = IIC_STATE_START; - solo_reg_write(solo_dev, SOLO_IIC_TXD, addr); - solo_i2c_flush(solo_dev, 1); -} - -static void solo_i2c_stop(struct solo_dev *solo_dev) -{ - solo_irq_off(solo_dev, SOLO_IRQ_IIC); - solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0); - solo_dev->i2c_state = IIC_STATE_STOP; - wake_up(&solo_dev->i2c_wait); -} - -static int solo_i2c_handle_read(struct solo_dev *solo_dev) -{ -prepare_read: - if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) { - solo_i2c_flush(solo_dev, 0); - return 0; - } - - solo_dev->i2c_msg_ptr = 0; - solo_dev->i2c_msg++; - solo_dev->i2c_msg_num--; - - if (solo_dev->i2c_msg_num == 0) { - solo_i2c_stop(solo_dev); - return 0; - } - - if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) { - solo_i2c_start(solo_dev); - } else { - if (solo_dev->i2c_msg->flags & I2C_M_RD) - goto prepare_read; - else - solo_i2c_stop(solo_dev); - } - - return 0; -} - -static int solo_i2c_handle_write(struct solo_dev *solo_dev) -{ -retry_write: - if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) { - solo_reg_write(solo_dev, SOLO_IIC_TXD, - solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr]); - solo_dev->i2c_msg_ptr++; - solo_i2c_flush(solo_dev, 1); - return 0; - } - - solo_dev->i2c_msg_ptr = 0; - solo_dev->i2c_msg++; - solo_dev->i2c_msg_num--; - - if (solo_dev->i2c_msg_num == 0) { - solo_i2c_stop(solo_dev); - return 0; - } - - if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) { - solo_i2c_start(solo_dev); - } else { - if (solo_dev->i2c_msg->flags & I2C_M_RD) - solo_i2c_stop(solo_dev); - else - goto retry_write; - } - - return 0; -} - -int solo_i2c_isr(struct solo_dev *solo_dev) -{ - u32 status = solo_reg_read(solo_dev, SOLO_IIC_CTRL); - int ret = -EINVAL; - - - if (CHK_FLAGS(status, SOLO_IIC_STATE_TRNS | SOLO_IIC_STATE_SIG_ERR) - || solo_dev->i2c_id < 0) { - solo_i2c_stop(solo_dev); - return -ENXIO; - } - - switch (solo_dev->i2c_state) { - case IIC_STATE_START: - if (solo_dev->i2c_msg->flags & I2C_M_RD) { - solo_dev->i2c_state = IIC_STATE_READ; - ret = solo_i2c_handle_read(solo_dev); - break; - } - - solo_dev->i2c_state = IIC_STATE_WRITE; - case IIC_STATE_WRITE: - ret = solo_i2c_handle_write(solo_dev); - break; - - case IIC_STATE_READ: - solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr] = - solo_reg_read(solo_dev, SOLO_IIC_RXD); - solo_dev->i2c_msg_ptr++; - - ret = solo_i2c_handle_read(solo_dev); - break; - - default: - solo_i2c_stop(solo_dev); - } - - return ret; -} - -static int solo_i2c_master_xfer(struct i2c_adapter *adap, - struct i2c_msg msgs[], int num) -{ - struct solo_dev *solo_dev = adap->algo_data; - unsigned long timeout; - int ret; - int i; - DEFINE_WAIT(wait); - - for (i = 0; i < SOLO_I2C_ADAPTERS; i++) { - if (&solo_dev->i2c_adap[i] == adap) - break; - } - - if (i == SOLO_I2C_ADAPTERS) - return num; /* XXX Right return value for failure? */ - - mutex_lock(&solo_dev->i2c_mutex); - solo_dev->i2c_id = i; - solo_dev->i2c_msg = msgs; - solo_dev->i2c_msg_num = num; - solo_dev->i2c_msg_ptr = 0; - - solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0); - solo_irq_on(solo_dev, SOLO_IRQ_IIC); - solo_i2c_start(solo_dev); - - timeout = HZ / 2; - - for (;;) { - prepare_to_wait(&solo_dev->i2c_wait, &wait, - TASK_INTERRUPTIBLE); - - if (solo_dev->i2c_state == IIC_STATE_STOP) - break; - - timeout = schedule_timeout(timeout); - if (!timeout) - break; - - if (signal_pending(current)) - break; - } - - finish_wait(&solo_dev->i2c_wait, &wait); - ret = num - solo_dev->i2c_msg_num; - solo_dev->i2c_state = IIC_STATE_IDLE; - solo_dev->i2c_id = -1; - - mutex_unlock(&solo_dev->i2c_mutex); - - return ret; -} - -static u32 solo_i2c_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C; -} - -static const struct i2c_algorithm solo_i2c_algo = { - .master_xfer = solo_i2c_master_xfer, - .functionality = solo_i2c_functionality, -}; - -int solo_i2c_init(struct solo_dev *solo_dev) -{ - int i; - int ret; - - solo_reg_write(solo_dev, SOLO_IIC_CFG, - SOLO_IIC_PRESCALE(8) | SOLO_IIC_ENABLE); - - solo_dev->i2c_id = -1; - solo_dev->i2c_state = IIC_STATE_IDLE; - init_waitqueue_head(&solo_dev->i2c_wait); - mutex_init(&solo_dev->i2c_mutex); - - for (i = 0; i < SOLO_I2C_ADAPTERS; i++) { - struct i2c_adapter *adap = &solo_dev->i2c_adap[i]; - - snprintf(adap->name, I2C_NAME_SIZE, "%s I2C %d", - SOLO6X10_NAME, i); - adap->algo = &solo_i2c_algo; - adap->algo_data = solo_dev; - adap->retries = 1; - adap->dev.parent = &solo_dev->pdev->dev; - - ret = i2c_add_adapter(adap); - if (ret) { - adap->algo_data = NULL; - break; - } - } - - if (ret) { - for (i = 0; i < SOLO_I2C_ADAPTERS; i++) { - if (!solo_dev->i2c_adap[i].algo_data) - break; - i2c_del_adapter(&solo_dev->i2c_adap[i]); - solo_dev->i2c_adap[i].algo_data = NULL; - } - return ret; - } - - return 0; -} - -void solo_i2c_exit(struct solo_dev *solo_dev) -{ - int i; - - for (i = 0; i < SOLO_I2C_ADAPTERS; i++) { - if (!solo_dev->i2c_adap[i].algo_data) - continue; - i2c_del_adapter(&solo_dev->i2c_adap[i]); - solo_dev->i2c_adap[i].algo_data = NULL; - } -} diff --git a/drivers/staging/media/solo6x10/solo6x10-jpeg.h b/drivers/staging/media/solo6x10/solo6x10-jpeg.h deleted file mode 100644 index c5218ceeabca..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-jpeg.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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 __SOLO6X10_JPEG_H -#define __SOLO6X10_JPEG_H - -static const unsigned char jpeg_header[] = { - 0xff, 0xd8, 0xff, 0xfe, 0x00, 0x0d, 0x42, 0x6c, - 0x75, 0x65, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79, - 0x20, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x20, 0x16, - 0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c, 0x1a, 0x1c, - 0x24, 0x22, 0x20, 0x26, 0x30, 0x50, 0x34, 0x30, - 0x2c, 0x2c, 0x30, 0x62, 0x46, 0x4a, 0x3a, 0x50, - 0x74, 0x66, 0x7a, 0x78, 0x72, 0x66, 0x70, 0x6e, - 0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88, 0xae, 0x8a, - 0x6e, 0x70, 0xa0, 0xda, 0xa2, 0xae, 0xbe, 0xc4, - 0xce, 0xd0, 0xce, 0x7c, 0x9a, 0xe2, 0xf2, 0xe0, - 0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6, 0xff, 0xdb, - 0x00, 0x43, 0x01, 0x22, 0x24, 0x24, 0x30, 0x2a, - 0x30, 0x5e, 0x34, 0x34, 0x5e, 0xc6, 0x84, 0x70, - 0x84, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xff, 0xc4, 0x01, 0xa2, 0x00, - 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, - 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, - 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, - 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, - 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, - 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, - 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, - 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, - 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, - 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, - 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, - 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, - 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, - 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, - 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, - 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, - 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, - 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, - 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, - 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, - 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, - 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x01, - 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x11, 0x00, 0x02, 0x01, - 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, - 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, - 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, - 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, - 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, - 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, - 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, - 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, - 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, - 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, - 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, - 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, - 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, - 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, - 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, - 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, - 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, - 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, - 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, - 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, - 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, - 0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x02, 0xc0, - 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, - 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, - 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 -}; - -/* This is the byte marker for the start of SOF0: 0xffc0 marker */ -#define SOF0_START 575 - -/* This is the byte marker for the start of the DQT */ -#define DQT_START 17 -#define DQT_LEN 138 -const unsigned char jpeg_dqt[4][DQT_LEN] = { - { - 0xff, 0xdb, 0x00, 0x43, 0x00, - 0x08, 0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, - 0x07, 0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, - 0x0d, 0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, - 0x0f, 0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, - 0x1c, 0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, - 0x2c, 0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, - 0x30, 0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, - 0x3d, 0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, - 0xff, 0xdb, 0x00, 0x43, 0x01, - 0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0d, - 0x0d, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32 - }, { - 0xff, 0xdb, 0x00, 0x43, 0x00, - 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, - 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, - 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, - 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, - 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44, - 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, - 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, - 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63, - 0xff, 0xdb, 0x00, 0x43, 0x01, - 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, - 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 - }, { - 0xff, 0xdb, 0x00, 0x43, 0x00, - 0x20, 0x16, 0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c, - 0x1a, 0x1c, 0x24, 0x22, 0x20, 0x26, 0x30, 0x50, - 0x34, 0x30, 0x2c, 0x2c, 0x30, 0x62, 0x46, 0x4a, - 0x3a, 0x50, 0x74, 0x66, 0x7a, 0x78, 0x72, 0x66, - 0x70, 0x6e, 0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88, - 0xae, 0x8a, 0x6e, 0x70, 0xa0, 0xda, 0xa2, 0xae, - 0xbe, 0xc4, 0xce, 0xd0, 0xce, 0x7c, 0x9a, 0xe2, - 0xf2, 0xe0, 0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6, - 0xff, 0xdb, 0x00, 0x43, 0x01, - 0x22, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34, - 0x34, 0x5e, 0xc6, 0x84, 0x70, 0x84, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6 - }, { - 0xff, 0xdb, 0x00, 0x43, 0x00, - 0x30, 0x21, 0x24, 0x2a, 0x24, 0x1e, 0x30, 0x2a, - 0x27, 0x2a, 0x36, 0x33, 0x30, 0x39, 0x48, 0x78, - 0x4e, 0x48, 0x42, 0x42, 0x48, 0x93, 0x69, 0x6f, - 0x57, 0x78, 0xae, 0x99, 0xb7, 0xb4, 0xab, 0x99, - 0xa8, 0xa5, 0xc0, 0xd8, 0xff, 0xea, 0xc0, 0xcc, - 0xff, 0xcf, 0xa5, 0xa8, 0xf0, 0xff, 0xf3, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xe7, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xdb, 0x00, 0x43, 0x01, - 0x33, 0x36, 0x36, 0x48, 0x3f, 0x48, 0x8d, 0x4e, - 0x4e, 0x8d, 0xff, 0xc6, 0xa8, 0xc6, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - } -}; - -#endif /* __SOLO6X10_JPEG_H */ diff --git a/drivers/staging/media/solo6x10/solo6x10-offsets.h b/drivers/staging/media/solo6x10/solo6x10-offsets.h deleted file mode 100644 index 13eeb4470dcf..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-offsets.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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 __SOLO6X10_OFFSETS_H -#define __SOLO6X10_OFFSETS_H - -#define SOLO_DISP_EXT_ADDR 0x00000000 -#define SOLO_DISP_EXT_SIZE 0x00480000 - -#define SOLO_EOSD_EXT_ADDR \ - (SOLO_DISP_EXT_ADDR + SOLO_DISP_EXT_SIZE) -#define SOLO_EOSD_EXT_SIZE(__solo) \ - (__solo->type == SOLO_DEV_6010 ? 0x10000 : 0x20000) -#define SOLO_EOSD_EXT_SIZE_MAX 0x20000 -#define SOLO_EOSD_EXT_AREA(__solo) \ - (SOLO_EOSD_EXT_SIZE(__solo) * 32) -#define SOLO_EOSD_EXT_ADDR_CHAN(__solo, ch) \ - (SOLO_EOSD_EXT_ADDR + SOLO_EOSD_EXT_SIZE(__solo) * (ch)) - -#define SOLO_MOTION_EXT_ADDR(__solo) \ - (SOLO_EOSD_EXT_ADDR + SOLO_EOSD_EXT_AREA(__solo)) -#define SOLO_MOTION_EXT_SIZE 0x00080000 - -#define SOLO_G723_EXT_ADDR(__solo) \ - (SOLO_MOTION_EXT_ADDR(__solo) + SOLO_MOTION_EXT_SIZE) -#define SOLO_G723_EXT_SIZE 0x00010000 - -#define SOLO_CAP_EXT_ADDR(__solo) \ - (SOLO_G723_EXT_ADDR(__solo) + SOLO_G723_EXT_SIZE) - -/* 18 is the maximum number of pages required for PAL@D1, the largest frame - * possible */ -#define SOLO_CAP_PAGE_SIZE (18 << 16) - -/* Always allow the encoder enough for 16 channels, even if we have less. The - * exception is if we have card with only 32Megs of memory. */ -#define SOLO_CAP_EXT_SIZE(__solo) \ - ((((__solo->sdram_size <= (32 << 20)) ? 4 : 16) + 1) \ - * SOLO_CAP_PAGE_SIZE) - -#define SOLO_EREF_EXT_ADDR(__solo) \ - (SOLO_CAP_EXT_ADDR(__solo) + SOLO_CAP_EXT_SIZE(__solo)) -#define SOLO_EREF_EXT_SIZE 0x00140000 -#define SOLO_EREF_EXT_AREA(__solo) \ - (SOLO_EREF_EXT_SIZE * __solo->nr_chans * 2) - -#define __SOLO_JPEG_MIN_SIZE(__solo) (__solo->nr_chans * 0x00080000) - -#define SOLO_MP4E_EXT_ADDR(__solo) \ - (SOLO_EREF_EXT_ADDR(__solo) + SOLO_EREF_EXT_AREA(__solo)) -#define SOLO_MP4E_EXT_SIZE(__solo) \ - max((__solo->nr_chans * 0x00080000), \ - min(((__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo)) - \ - __SOLO_JPEG_MIN_SIZE(__solo)), 0x00ff0000)) - -#define __SOLO_JPEG_MIN_SIZE(__solo) (__solo->nr_chans * 0x00080000) -#define SOLO_JPEG_EXT_ADDR(__solo) \ - (SOLO_MP4E_EXT_ADDR(__solo) + SOLO_MP4E_EXT_SIZE(__solo)) -#define SOLO_JPEG_EXT_SIZE(__solo) \ - max(__SOLO_JPEG_MIN_SIZE(__solo), \ - min((__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo)), 0x00ff0000)) - -#define SOLO_SDRAM_END(__solo) \ - (SOLO_JPEG_EXT_ADDR(__solo) + SOLO_JPEG_EXT_SIZE(__solo)) - -#endif /* __SOLO6X10_OFFSETS_H */ diff --git a/drivers/staging/media/solo6x10/solo6x10-p2m.c b/drivers/staging/media/solo6x10/solo6x10-p2m.c deleted file mode 100644 index 7f2f2472655b..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-p2m.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> - -#include "solo6x10.h" - -static int multi_p2m; -module_param(multi_p2m, uint, 0644); -MODULE_PARM_DESC(multi_p2m, - "Use multiple P2M DMA channels (default: no, 6010-only)"); - -static int desc_mode; -module_param(desc_mode, uint, 0644); -MODULE_PARM_DESC(desc_mode, - "Allow use of descriptor mode DMA (default: no, 6010-only)"); - -int solo_p2m_dma(struct solo_dev *solo_dev, int wr, - void *sys_addr, u32 ext_addr, u32 size, - int repeat, u32 ext_size) -{ - dma_addr_t dma_addr; - int ret; - - if (WARN_ON_ONCE((unsigned long)sys_addr & 0x03)) - return -EINVAL; - if (WARN_ON_ONCE(!size)) - return -EINVAL; - - dma_addr = pci_map_single(solo_dev->pdev, sys_addr, size, - wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(solo_dev->pdev, dma_addr)) - return -ENOMEM; - - ret = solo_p2m_dma_t(solo_dev, wr, dma_addr, ext_addr, size, - repeat, ext_size); - - pci_unmap_single(solo_dev->pdev, dma_addr, size, - wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - - return ret; -} - -/* Mutex must be held for p2m_id before calling this!! */ -int solo_p2m_dma_desc(struct solo_dev *solo_dev, - struct solo_p2m_desc *desc, dma_addr_t desc_dma, - int desc_cnt) -{ - struct solo_p2m_dev *p2m_dev; - unsigned int timeout; - unsigned int config = 0; - int ret = 0; - int p2m_id = 0; - - /* Get next ID. According to Softlogic, 6110 has problems on !=0 P2M */ - if (solo_dev->type != SOLO_DEV_6110 && multi_p2m) { - p2m_id = atomic_inc_return(&solo_dev->p2m_count) % SOLO_NR_P2M; - if (p2m_id < 0) - p2m_id = -p2m_id; - } - - p2m_dev = &solo_dev->p2m_dev[p2m_id]; - - if (mutex_lock_interruptible(&p2m_dev->mutex)) - return -EINTR; - - reinit_completion(&p2m_dev->completion); - p2m_dev->error = 0; - - if (desc_cnt > 1 && solo_dev->type != SOLO_DEV_6110 && desc_mode) { - /* For 6010 with more than one desc, we can do a one-shot */ - p2m_dev->desc_count = p2m_dev->desc_idx = 0; - config = solo_reg_read(solo_dev, SOLO_P2M_CONFIG(p2m_id)); - - solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(p2m_id), desc_dma); - solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(p2m_id), desc_cnt); - solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config | - SOLO_P2M_DESC_MODE); - } else { - /* For single descriptors and 6110, we need to run each desc */ - p2m_dev->desc_count = desc_cnt; - p2m_dev->desc_idx = 1; - p2m_dev->descs = desc; - - solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(p2m_id), - desc[1].dma_addr); - solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(p2m_id), - desc[1].ext_addr); - solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(p2m_id), - desc[1].cfg); - solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id), - desc[1].ctrl); - } - - timeout = wait_for_completion_timeout(&p2m_dev->completion, - solo_dev->p2m_jiffies); - - if (WARN_ON_ONCE(p2m_dev->error)) - ret = -EIO; - else if (timeout == 0) { - solo_dev->p2m_timeouts++; - ret = -EAGAIN; - } - - solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id), 0); - - /* Don't write here for the no_desc_mode case, because config is 0. - * We can't test no_desc_mode again, it might race. */ - if (desc_cnt > 1 && solo_dev->type != SOLO_DEV_6110 && config) - solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config); - - mutex_unlock(&p2m_dev->mutex); - - return ret; -} - -void solo_p2m_fill_desc(struct solo_p2m_desc *desc, int wr, - dma_addr_t dma_addr, u32 ext_addr, u32 size, - int repeat, u32 ext_size) -{ - WARN_ON_ONCE(dma_addr & 0x03); - WARN_ON_ONCE(!size); - - desc->cfg = SOLO_P2M_COPY_SIZE(size >> 2); - desc->ctrl = SOLO_P2M_BURST_SIZE(SOLO_P2M_BURST_256) | - (wr ? SOLO_P2M_WRITE : 0) | SOLO_P2M_TRANS_ON; - - if (repeat) { - desc->cfg |= SOLO_P2M_EXT_INC(ext_size >> 2); - desc->ctrl |= SOLO_P2M_PCI_INC(size >> 2) | - SOLO_P2M_REPEAT(repeat); - } - - desc->dma_addr = dma_addr; - desc->ext_addr = ext_addr; -} - -int solo_p2m_dma_t(struct solo_dev *solo_dev, int wr, - dma_addr_t dma_addr, u32 ext_addr, u32 size, - int repeat, u32 ext_size) -{ - struct solo_p2m_desc desc[2]; - - solo_p2m_fill_desc(&desc[1], wr, dma_addr, ext_addr, size, repeat, - ext_size); - - /* No need for desc_dma since we know it is a single-shot */ - return solo_p2m_dma_desc(solo_dev, desc, 0, 1); -} - -void solo_p2m_isr(struct solo_dev *solo_dev, int id) -{ - struct solo_p2m_dev *p2m_dev = &solo_dev->p2m_dev[id]; - struct solo_p2m_desc *desc; - - if (p2m_dev->desc_count <= p2m_dev->desc_idx) { - complete(&p2m_dev->completion); - return; - } - - /* Setup next descriptor */ - p2m_dev->desc_idx++; - desc = &p2m_dev->descs[p2m_dev->desc_idx]; - - solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0); - solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(id), desc->dma_addr); - solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(id), desc->ext_addr); - solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(id), desc->cfg); - solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), desc->ctrl); -} - -void solo_p2m_error_isr(struct solo_dev *solo_dev) -{ - unsigned int err = solo_reg_read(solo_dev, SOLO_PCI_ERR); - struct solo_p2m_dev *p2m_dev; - int i; - - if (!(err & (SOLO_PCI_ERR_P2M | SOLO_PCI_ERR_P2M_DESC))) - return; - - for (i = 0; i < SOLO_NR_P2M; i++) { - p2m_dev = &solo_dev->p2m_dev[i]; - p2m_dev->error = 1; - solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0); - complete(&p2m_dev->completion); - } -} - -void solo_p2m_exit(struct solo_dev *solo_dev) -{ - int i; - - for (i = 0; i < SOLO_NR_P2M; i++) - solo_irq_off(solo_dev, SOLO_IRQ_P2M(i)); -} - -static int solo_p2m_test(struct solo_dev *solo_dev, int base, int size) -{ - u32 *wr_buf; - u32 *rd_buf; - int i; - int ret = -EIO; - int order = get_order(size); - - wr_buf = (u32 *)__get_free_pages(GFP_KERNEL, order); - if (wr_buf == NULL) - return -1; - - rd_buf = (u32 *)__get_free_pages(GFP_KERNEL, order); - if (rd_buf == NULL) { - free_pages((unsigned long)wr_buf, order); - return -1; - } - - for (i = 0; i < (size >> 3); i++) - *(wr_buf + i) = (i << 16) | (i + 1); - - for (i = (size >> 3); i < (size >> 2); i++) - *(wr_buf + i) = ~((i << 16) | (i + 1)); - - memset(rd_buf, 0x55, size); - - if (solo_p2m_dma(solo_dev, 1, wr_buf, base, size, 0, 0)) - goto test_fail; - - if (solo_p2m_dma(solo_dev, 0, rd_buf, base, size, 0, 0)) - goto test_fail; - - for (i = 0; i < (size >> 2); i++) { - if (*(wr_buf + i) != *(rd_buf + i)) - goto test_fail; - } - - ret = 0; - -test_fail: - free_pages((unsigned long)wr_buf, order); - free_pages((unsigned long)rd_buf, order); - - return ret; -} - -int solo_p2m_init(struct solo_dev *solo_dev) -{ - struct solo_p2m_dev *p2m_dev; - int i; - - for (i = 0; i < SOLO_NR_P2M; i++) { - p2m_dev = &solo_dev->p2m_dev[i]; - - mutex_init(&p2m_dev->mutex); - init_completion(&p2m_dev->completion); - - solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0); - solo_reg_write(solo_dev, SOLO_P2M_CONFIG(i), - SOLO_P2M_CSC_16BIT_565 | - SOLO_P2M_DESC_INTR_OPT | - SOLO_P2M_DMA_INTERVAL(0) | - SOLO_P2M_PCI_MASTER_MODE); - solo_irq_on(solo_dev, SOLO_IRQ_P2M(i)); - } - - /* Find correct SDRAM size */ - for (solo_dev->sdram_size = 0, i = 2; i >= 0; i--) { - solo_reg_write(solo_dev, SOLO_DMA_CTRL, - SOLO_DMA_CTRL_REFRESH_CYCLE(1) | - SOLO_DMA_CTRL_SDRAM_SIZE(i) | - SOLO_DMA_CTRL_SDRAM_CLK_INVERT | - SOLO_DMA_CTRL_READ_CLK_SELECT | - SOLO_DMA_CTRL_LATENCY(1)); - - solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config | - SOLO_SYS_CFG_RESET); - solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config); - - switch (i) { - case 2: - if (solo_p2m_test(solo_dev, 0x07ff0000, 0x00010000) || - solo_p2m_test(solo_dev, 0x05ff0000, 0x00010000)) - continue; - break; - - case 1: - if (solo_p2m_test(solo_dev, 0x03ff0000, 0x00010000)) - continue; - break; - - default: - if (solo_p2m_test(solo_dev, 0x01ff0000, 0x00010000)) - continue; - } - - solo_dev->sdram_size = (32 << 20) << i; - break; - } - - if (!solo_dev->sdram_size) { - dev_err(&solo_dev->pdev->dev, "Error detecting SDRAM size\n"); - return -EIO; - } - - if (SOLO_SDRAM_END(solo_dev) > solo_dev->sdram_size) { - dev_err(&solo_dev->pdev->dev, - "SDRAM is not large enough (%u < %u)\n", - solo_dev->sdram_size, SOLO_SDRAM_END(solo_dev)); - return -EIO; - } - - return 0; -} diff --git a/drivers/staging/media/solo6x10/solo6x10-regs.h b/drivers/staging/media/solo6x10/solo6x10-regs.h deleted file mode 100644 index 428f6c951180..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-regs.h +++ /dev/null @@ -1,639 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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 __SOLO6X10_REGISTERS_H -#define __SOLO6X10_REGISTERS_H - -#include "solo6x10-offsets.h" - -/* Global 6010 system configuration */ -#define SOLO_SYS_CFG 0x0000 -#define SOLO_SYS_CFG_FOUT_EN 0x00000001 -#define SOLO_SYS_CFG_PLL_BYPASS 0x00000002 -#define SOLO_SYS_CFG_PLL_PWDN 0x00000004 -#define SOLO_SYS_CFG_OUTDIV(__n) (((__n) & 0x003) << 3) -#define SOLO_SYS_CFG_FEEDBACKDIV(__n) (((__n) & 0x1ff) << 5) -#define SOLO_SYS_CFG_INPUTDIV(__n) (((__n) & 0x01f) << 14) -#define SOLO_SYS_CFG_CLOCK_DIV 0x00080000 -#define SOLO_SYS_CFG_NCLK_DELAY(__n) (((__n) & 0x003) << 24) -#define SOLO_SYS_CFG_PCLK_DELAY(__n) (((__n) & 0x00f) << 26) -#define SOLO_SYS_CFG_SDRAM64BIT 0x40000000 -#define SOLO_SYS_CFG_RESET 0x80000000 - -#define SOLO_DMA_CTRL 0x0004 -#define SOLO_DMA_CTRL_REFRESH_CYCLE(n) ((n)<<8) -/* 0=16/32MB, 1=32/64MB, 2=64/128MB, 3=128/256MB */ -#define SOLO_DMA_CTRL_SDRAM_SIZE(n) ((n)<<6) -#define SOLO_DMA_CTRL_SDRAM_CLK_INVERT (1<<5) -#define SOLO_DMA_CTRL_STROBE_SELECT (1<<4) -#define SOLO_DMA_CTRL_READ_DATA_SELECT (1<<3) -#define SOLO_DMA_CTRL_READ_CLK_SELECT (1<<2) -#define SOLO_DMA_CTRL_LATENCY(n) ((n)<<0) - -/* Some things we set in this are undocumented. Why Softlogic?!?! */ -#define SOLO_DMA_CTRL1 0x0008 - -#define SOLO_SYS_VCLK 0x000C -#define SOLO_VCLK_INVERT (1<<22) -/* 0=sys_clk/4, 1=sys_clk/2, 2=clk_in/2 of system input */ -#define SOLO_VCLK_SELECT(n) ((n)<<20) -#define SOLO_VCLK_VIN1415_DELAY(n) ((n)<<14) -#define SOLO_VCLK_VIN1213_DELAY(n) ((n)<<12) -#define SOLO_VCLK_VIN1011_DELAY(n) ((n)<<10) -#define SOLO_VCLK_VIN0809_DELAY(n) ((n)<<8) -#define SOLO_VCLK_VIN0607_DELAY(n) ((n)<<6) -#define SOLO_VCLK_VIN0405_DELAY(n) ((n)<<4) -#define SOLO_VCLK_VIN0203_DELAY(n) ((n)<<2) -#define SOLO_VCLK_VIN0001_DELAY(n) ((n)<<0) - -#define SOLO_IRQ_STAT 0x0010 -#define SOLO_IRQ_MASK 0x0014 -#define SOLO_IRQ_P2M(n) (1<<((n)+17)) -#define SOLO_IRQ_GPIO (1<<16) -#define SOLO_IRQ_VIDEO_LOSS (1<<15) -#define SOLO_IRQ_VIDEO_IN (1<<14) -#define SOLO_IRQ_MOTION (1<<13) -#define SOLO_IRQ_ATA_CMD (1<<12) -#define SOLO_IRQ_ATA_DIR (1<<11) -#define SOLO_IRQ_PCI_ERR (1<<10) -#define SOLO_IRQ_PS2_1 (1<<9) -#define SOLO_IRQ_PS2_0 (1<<8) -#define SOLO_IRQ_SPI (1<<7) -#define SOLO_IRQ_IIC (1<<6) -#define SOLO_IRQ_UART(n) (1<<((n) + 4)) -#define SOLO_IRQ_G723 (1<<3) -#define SOLO_IRQ_DECODER (1<<1) -#define SOLO_IRQ_ENCODER (1<<0) - -#define SOLO_CHIP_OPTION 0x001C -#define SOLO_CHIP_ID_MASK 0x00000007 - -#define SOLO_PLL_CONFIG 0x0020 /* 6110 Only */ - -#define SOLO_EEPROM_CTRL 0x0060 -#define SOLO_EEPROM_ACCESS_EN (1<<7) -#define SOLO_EEPROM_CS (1<<3) -#define SOLO_EEPROM_CLK (1<<2) -#define SOLO_EEPROM_DO (1<<1) -#define SOLO_EEPROM_DI (1<<0) -#define SOLO_EEPROM_ENABLE (SOLO_EEPROM_ACCESS_EN | SOLO_EEPROM_CS) - -#define SOLO_PCI_ERR 0x0070 -#define SOLO_PCI_ERR_FATAL 0x00000001 -#define SOLO_PCI_ERR_PARITY 0x00000002 -#define SOLO_PCI_ERR_TARGET 0x00000004 -#define SOLO_PCI_ERR_TIMEOUT 0x00000008 -#define SOLO_PCI_ERR_P2M 0x00000010 -#define SOLO_PCI_ERR_ATA 0x00000020 -#define SOLO_PCI_ERR_P2M_DESC 0x00000040 -#define SOLO_PCI_ERR_FSM0(__s) (((__s) >> 16) & 0x0f) -#define SOLO_PCI_ERR_FSM1(__s) (((__s) >> 20) & 0x0f) -#define SOLO_PCI_ERR_FSM2(__s) (((__s) >> 24) & 0x1f) - -#define SOLO_P2M_BASE 0x0080 - -#define SOLO_P2M_CONFIG(n) (0x0080 + ((n)*0x20)) -#define SOLO_P2M_DMA_INTERVAL(n) ((n)<<6)/* N*32 clocks */ -#define SOLO_P2M_CSC_BYTE_REORDER (1<<5) /* BGR -> RGB */ -/* 0:r=[14:10] g=[9:5] b=[4:0], 1:r=[15:11] g=[10:5] b=[4:0] */ -#define SOLO_P2M_CSC_16BIT_565 (1<<4) -#define SOLO_P2M_UV_SWAP (1<<3) -#define SOLO_P2M_PCI_MASTER_MODE (1<<2) -#define SOLO_P2M_DESC_INTR_OPT (1<<1) /* 1:Empty, 0:Each */ -#define SOLO_P2M_DESC_MODE (1<<0) - -#define SOLO_P2M_DES_ADR(n) (0x0084 + ((n)*0x20)) - -#define SOLO_P2M_DESC_ID(n) (0x0088 + ((n)*0x20)) -#define SOLO_P2M_UPDATE_ID(n) ((n)<<0) - -#define SOLO_P2M_STATUS(n) (0x008C + ((n)*0x20)) -#define SOLO_P2M_COMMAND_DONE (1<<8) -#define SOLO_P2M_CURRENT_ID(stat) (0xff & (stat)) - -#define SOLO_P2M_CONTROL(n) (0x0090 + ((n)*0x20)) -#define SOLO_P2M_PCI_INC(n) ((n)<<20) -#define SOLO_P2M_REPEAT(n) ((n)<<10) -/* 0:512, 1:256, 2:128, 3:64, 4:32, 5:128(2page) */ -#define SOLO_P2M_BURST_SIZE(n) ((n)<<7) -#define SOLO_P2M_BURST_512 0 -#define SOLO_P2M_BURST_256 1 -#define SOLO_P2M_BURST_128 2 -#define SOLO_P2M_BURST_64 3 -#define SOLO_P2M_BURST_32 4 -#define SOLO_P2M_CSC_16BIT (1<<6) /* 0:24bit, 1:16bit */ -/* 0:Y[0]<-0(OFF), 1:Y[0]<-1(ON), 2:Y[0]<-G[0], 3:Y[0]<-Bit[15] */ -#define SOLO_P2M_ALPHA_MODE(n) ((n)<<4) -#define SOLO_P2M_CSC_ON (1<<3) -#define SOLO_P2M_INTERRUPT_REQ (1<<2) -#define SOLO_P2M_WRITE (1<<1) -#define SOLO_P2M_TRANS_ON (1<<0) - -#define SOLO_P2M_EXT_CFG(n) (0x0094 + ((n)*0x20)) -#define SOLO_P2M_EXT_INC(n) ((n)<<20) -#define SOLO_P2M_COPY_SIZE(n) ((n)<<0) - -#define SOLO_P2M_TAR_ADR(n) (0x0098 + ((n)*0x20)) - -#define SOLO_P2M_EXT_ADR(n) (0x009C + ((n)*0x20)) - -#define SOLO_P2M_BUFFER(i) (0x2000 + ((i)*4)) - -#define SOLO_VI_CH_SWITCH_0 0x0100 -#define SOLO_VI_CH_SWITCH_1 0x0104 -#define SOLO_VI_CH_SWITCH_2 0x0108 - -#define SOLO_VI_CH_ENA 0x010C -#define SOLO_VI_CH_FORMAT 0x0110 -#define SOLO_VI_FD_SEL_MASK(n) ((n)<<16) -#define SOLO_VI_PROG_MASK(n) ((n)<<0) - -#define SOLO_VI_FMT_CFG 0x0114 -#define SOLO_VI_FMT_CHECK_VCOUNT (1<<31) -#define SOLO_VI_FMT_CHECK_HCOUNT (1<<30) -#define SOLO_VI_FMT_TEST_SIGNAL (1<<28) - -#define SOLO_VI_PAGE_SW 0x0118 -#define SOLO_FI_INV_DISP_LIVE(n) ((n)<<8) -#define SOLO_FI_INV_DISP_OUT(n) ((n)<<7) -#define SOLO_DISP_SYNC_FI(n) ((n)<<6) -#define SOLO_PIP_PAGE_ADD(n) ((n)<<3) -#define SOLO_NORMAL_PAGE_ADD(n) ((n)<<0) - -#define SOLO_VI_ACT_I_P 0x011C -#define SOLO_VI_ACT_I_S 0x0120 -#define SOLO_VI_ACT_P 0x0124 -#define SOLO_VI_FI_INVERT (1<<31) -#define SOLO_VI_H_START(n) ((n)<<21) -#define SOLO_VI_V_START(n) ((n)<<11) -#define SOLO_VI_V_STOP(n) ((n)<<0) - -#define SOLO_VI_STATUS0 0x0128 -#define SOLO_VI_STATUS0_PAGE(__n) ((__n) & 0x07) -#define SOLO_VI_STATUS1 0x012C - -/* XXX: Might be better off in kernel level disp.h */ -#define DISP_PAGE(stat) ((stat) & 0x07) - -#define SOLO_VI_PB_CONFIG 0x0130 -#define SOLO_VI_PB_USER_MODE (1<<1) -#define SOLO_VI_PB_PAL (1<<0) -#define SOLO_VI_PB_RANGE_HV 0x0134 -#define SOLO_VI_PB_HSIZE(h) ((h)<<12) -#define SOLO_VI_PB_VSIZE(v) ((v)<<0) -#define SOLO_VI_PB_ACT_H 0x0138 -#define SOLO_VI_PB_HSTART(n) ((n)<<12) -#define SOLO_VI_PB_HSTOP(n) ((n)<<0) -#define SOLO_VI_PB_ACT_V 0x013C -#define SOLO_VI_PB_VSTART(n) ((n)<<12) -#define SOLO_VI_PB_VSTOP(n) ((n)<<0) - -#define SOLO_VI_MOSAIC(ch) (0x0140 + ((ch)*4)) -#define SOLO_VI_MOSAIC_SX(x) ((x)<<24) -#define SOLO_VI_MOSAIC_EX(x) ((x)<<16) -#define SOLO_VI_MOSAIC_SY(x) ((x)<<8) -#define SOLO_VI_MOSAIC_EY(x) ((x)<<0) - -#define SOLO_VI_WIN_CTRL0(ch) (0x0180 + ((ch)*4)) -#define SOLO_VI_WIN_CTRL1(ch) (0x01C0 + ((ch)*4)) - -#define SOLO_VI_WIN_CHANNEL(n) ((n)<<28) - -#define SOLO_VI_WIN_PIP(n) ((n)<<27) -#define SOLO_VI_WIN_SCALE(n) ((n)<<24) - -#define SOLO_VI_WIN_SX(x) ((x)<<12) -#define SOLO_VI_WIN_EX(x) ((x)<<0) - -#define SOLO_VI_WIN_SY(x) ((x)<<12) -#define SOLO_VI_WIN_EY(x) ((x)<<0) - -#define SOLO_VI_WIN_ON(ch) (0x0200 + ((ch)*4)) - -#define SOLO_VI_WIN_SW 0x0240 -#define SOLO_VI_WIN_LIVE_AUTO_MUTE 0x0244 - -#define SOLO_VI_MOT_ADR 0x0260 -#define SOLO_VI_MOTION_EN(mask) ((mask)<<16) -#define SOLO_VI_MOT_CTRL 0x0264 -#define SOLO_VI_MOTION_FRAME_COUNT(n) ((n)<<24) -#define SOLO_VI_MOTION_SAMPLE_LENGTH(n) ((n)<<16) -#define SOLO_VI_MOTION_INTR_START_STOP (1<<15) -#define SOLO_VI_MOTION_FREEZE_DATA (1<<14) -#define SOLO_VI_MOTION_SAMPLE_COUNT(n) ((n)<<0) -#define SOLO_VI_MOT_CLEAR 0x0268 -#define SOLO_VI_MOT_STATUS 0x026C -#define SOLO_VI_MOTION_CNT(n) ((n)<<0) -#define SOLO_VI_MOTION_BORDER 0x0270 -#define SOLO_VI_MOTION_BAR 0x0274 -#define SOLO_VI_MOTION_Y_SET (1<<29) -#define SOLO_VI_MOTION_Y_ADD (1<<28) -#define SOLO_VI_MOTION_CB_SET (1<<27) -#define SOLO_VI_MOTION_CB_ADD (1<<26) -#define SOLO_VI_MOTION_CR_SET (1<<25) -#define SOLO_VI_MOTION_CR_ADD (1<<24) -#define SOLO_VI_MOTION_Y_VALUE(v) ((v)<<16) -#define SOLO_VI_MOTION_CB_VALUE(v) ((v)<<8) -#define SOLO_VI_MOTION_CR_VALUE(v) ((v)<<0) - -#define SOLO_VO_FMT_ENC 0x0300 -#define SOLO_VO_SCAN_MODE_PROGRESSIVE (1<<31) -#define SOLO_VO_FMT_TYPE_PAL (1<<30) -#define SOLO_VO_FMT_TYPE_NTSC 0 -#define SOLO_VO_USER_SET (1<<29) - -#define SOLO_VO_FI_CHANGE (1<<20) -#define SOLO_VO_USER_COLOR_SET_VSYNC (1<<19) -#define SOLO_VO_USER_COLOR_SET_HSYNC (1<<18) -#define SOLO_VO_USER_COLOR_SET_NAH (1<<17) -#define SOLO_VO_USER_COLOR_SET_NAV (1<<16) -#define SOLO_VO_NA_COLOR_Y(Y) ((Y)<<8) -#define SOLO_VO_NA_COLOR_CB(CB) (((CB)/16)<<4) -#define SOLO_VO_NA_COLOR_CR(CR) (((CR)/16)<<0) - -#define SOLO_VO_ACT_H 0x0304 -#define SOLO_VO_H_BLANK(n) ((n)<<22) -#define SOLO_VO_H_START(n) ((n)<<11) -#define SOLO_VO_H_STOP(n) ((n)<<0) - -#define SOLO_VO_ACT_V 0x0308 -#define SOLO_VO_V_BLANK(n) ((n)<<22) -#define SOLO_VO_V_START(n) ((n)<<11) -#define SOLO_VO_V_STOP(n) ((n)<<0) - -#define SOLO_VO_RANGE_HV 0x030C -#define SOLO_VO_SYNC_INVERT (1<<24) -#define SOLO_VO_HSYNC_INVERT (1<<23) -#define SOLO_VO_VSYNC_INVERT (1<<22) -#define SOLO_VO_H_LEN(n) ((n)<<11) -#define SOLO_VO_V_LEN(n) ((n)<<0) - -#define SOLO_VO_DISP_CTRL 0x0310 -#define SOLO_VO_DISP_ON (1<<31) -#define SOLO_VO_DISP_ERASE_COUNT(n) ((n&0xf)<<24) -#define SOLO_VO_DISP_DOUBLE_SCAN (1<<22) -#define SOLO_VO_DISP_SINGLE_PAGE (1<<21) -#define SOLO_VO_DISP_BASE(n) (((n)>>16) & 0xffff) - -#define SOLO_VO_DISP_ERASE 0x0314 -#define SOLO_VO_DISP_ERASE_ON (1<<0) - -#define SOLO_VO_ZOOM_CTRL 0x0318 -#define SOLO_VO_ZOOM_VER_ON (1<<24) -#define SOLO_VO_ZOOM_HOR_ON (1<<23) -#define SOLO_VO_ZOOM_V_COMP (1<<22) -#define SOLO_VO_ZOOM_SX(h) (((h)/2)<<11) -#define SOLO_VO_ZOOM_SY(v) (((v)/2)<<0) - -#define SOLO_VO_FREEZE_CTRL 0x031C -#define SOLO_VO_FREEZE_ON (1<<1) -#define SOLO_VO_FREEZE_INTERPOLATION (1<<0) - -#define SOLO_VO_BKG_COLOR 0x0320 -#define SOLO_BG_Y(y) ((y)<<16) -#define SOLO_BG_U(u) ((u)<<8) -#define SOLO_BG_V(v) ((v)<<0) - -#define SOLO_VO_DEINTERLACE 0x0324 -#define SOLO_VO_DEINTERLACE_THRESHOLD(n) ((n)<<8) -#define SOLO_VO_DEINTERLACE_EDGE_VALUE(n) ((n)<<0) - -#define SOLO_VO_BORDER_LINE_COLOR 0x0330 -#define SOLO_VO_BORDER_FILL_COLOR 0x0334 -#define SOLO_VO_BORDER_LINE_MASK 0x0338 -#define SOLO_VO_BORDER_FILL_MASK 0x033c - -#define SOLO_VO_BORDER_X(n) (0x0340+((n)*4)) -#define SOLO_VO_BORDER_Y(n) (0x0354+((n)*4)) - -#define SOLO_VO_CELL_EXT_SET 0x0368 -#define SOLO_VO_CELL_EXT_START 0x036c -#define SOLO_VO_CELL_EXT_STOP 0x0370 - -#define SOLO_VO_CELL_EXT_SET2 0x0374 -#define SOLO_VO_CELL_EXT_START2 0x0378 -#define SOLO_VO_CELL_EXT_STOP2 0x037c - -#define SOLO_VO_RECTANGLE_CTRL(n) (0x0368+((n)*12)) -#define SOLO_VO_RECTANGLE_START(n) (0x036c+((n)*12)) -#define SOLO_VO_RECTANGLE_STOP(n) (0x0370+((n)*12)) - -#define SOLO_VO_CURSOR_POS (0x0380) -#define SOLO_VO_CURSOR_CLR (0x0384) -#define SOLO_VO_CURSOR_CLR2 (0x0388) -#define SOLO_VO_CURSOR_MASK(id) (0x0390+((id)*4)) - -#define SOLO_VO_EXPANSION(id) (0x0250+((id)*4)) - -#define SOLO_OSG_CONFIG 0x03E0 -#define SOLO_VO_OSG_ON (1<<31) -#define SOLO_VO_OSG_COLOR_MUTE (1<<28) -#define SOLO_VO_OSG_ALPHA_RATE(n) ((n)<<22) -#define SOLO_VO_OSG_ALPHA_BG_RATE(n) ((n)<<16) -#define SOLO_VO_OSG_BASE(offset) (((offset)>>16)&0xffff) - -#define SOLO_OSG_ERASE 0x03E4 -#define SOLO_OSG_ERASE_ON (0x80) -#define SOLO_OSG_ERASE_OFF (0x00) - -#define SOLO_VO_OSG_BLINK 0x03E8 -#define SOLO_VO_OSG_BLINK_ON (1<<1) -#define SOLO_VO_OSG_BLINK_INTREVAL18 (1<<0) - -#define SOLO_CAP_BASE 0x0400 -#define SOLO_CAP_MAX_PAGE(n) ((n)<<16) -#define SOLO_CAP_BASE_ADDR(n) ((n)<<0) -#define SOLO_CAP_BTW 0x0404 -#define SOLO_CAP_PROG_BANDWIDTH(n) ((n)<<8) -#define SOLO_CAP_MAX_BANDWIDTH(n) ((n)<<0) - -#define SOLO_DIM_SCALE1 0x0408 -#define SOLO_DIM_SCALE2 0x040C -#define SOLO_DIM_SCALE3 0x0410 -#define SOLO_DIM_SCALE4 0x0414 -#define SOLO_DIM_SCALE5 0x0418 -#define SOLO_DIM_V_MB_NUM_FRAME(n) ((n)<<16) -#define SOLO_DIM_V_MB_NUM_FIELD(n) ((n)<<8) -#define SOLO_DIM_H_MB_NUM(n) ((n)<<0) - -#define SOLO_DIM_PROG 0x041C -#define SOLO_CAP_STATUS 0x0420 - -#define SOLO_CAP_CH_SCALE(ch) (0x0440+((ch)*4)) -#define SOLO_CAP_CH_COMP_ENA_E(ch) (0x0480+((ch)*4)) -#define SOLO_CAP_CH_INTV(ch) (0x04C0+((ch)*4)) -#define SOLO_CAP_CH_INTV_E(ch) (0x0500+((ch)*4)) - - -#define SOLO_VE_CFG0 0x0610 -#define SOLO_VE_TWO_PAGE_MODE (1<<31) -#define SOLO_VE_INTR_CTRL(n) ((n)<<24) -#define SOLO_VE_BLOCK_SIZE(n) ((n)<<16) -#define SOLO_VE_BLOCK_BASE(n) ((n)<<0) - -#define SOLO_VE_CFG1 0x0614 -#define SOLO_VE_BYTE_ALIGN(n) ((n)<<24) -#define SOLO_VE_INSERT_INDEX (1<<18) -#define SOLO_VE_MOTION_MODE(n) ((n)<<16) -#define SOLO_VE_MOTION_BASE(n) ((n)<<0) -#define SOLO_VE_MPEG_SIZE_H(n) ((n)<<28) /* 6110 Only */ -#define SOLO_VE_JPEG_SIZE_H(n) ((n)<<20) /* 6110 Only */ -#define SOLO_VE_INSERT_INDEX_JPEG (1<<19) /* 6110 Only */ - -#define SOLO_VE_WMRK_POLY 0x061C -#define SOLO_VE_VMRK_INIT_KEY 0x0620 -#define SOLO_VE_WMRK_STRL 0x0624 -#define SOLO_VE_ENCRYP_POLY 0x0628 -#define SOLO_VE_ENCRYP_INIT 0x062C -#define SOLO_VE_ATTR 0x0630 -#define SOLO_VE_LITTLE_ENDIAN (1<<31) -#define SOLO_COMP_ATTR_RN (1<<30) -#define SOLO_COMP_ATTR_FCODE(n) ((n)<<27) -#define SOLO_COMP_TIME_INC(n) ((n)<<25) -#define SOLO_COMP_TIME_WIDTH(n) ((n)<<21) -#define SOLO_DCT_INTERVAL(n) ((n)<<16) -#define SOLO_VE_COMPT_MOT 0x0634 /* 6110 Only */ - -#define SOLO_VE_STATE(n) (0x0640+((n)*4)) - -#define SOLO_VE_JPEG_QP_TBL 0x0670 -#define SOLO_VE_JPEG_QP_CH_L 0x0674 -#define SOLO_VE_JPEG_QP_CH_H 0x0678 -#define SOLO_VE_JPEG_CFG 0x067C -#define SOLO_VE_JPEG_CTRL 0x0680 -#define SOLO_VE_CODE_ENCRYPT 0x0684 /* 6110 Only */ -#define SOLO_VE_JPEG_CFG1 0x0688 /* 6110 Only */ -#define SOLO_VE_WMRK_ENABLE 0x068C /* 6110 Only */ -#define SOLO_VE_OSD_CH 0x0690 -#define SOLO_VE_OSD_BASE 0x0694 -#define SOLO_VE_OSD_CLR 0x0698 -#define SOLO_VE_OSD_OPT 0x069C -#define SOLO_VE_OSD_V_DOUBLE (1<<16) /* 6110 Only */ -#define SOLO_VE_OSD_H_SHADOW (1<<15) -#define SOLO_VE_OSD_V_SHADOW (1<<14) -#define SOLO_VE_OSD_H_OFFSET(n) ((n & 0x7f)<<7) -#define SOLO_VE_OSD_V_OFFSET(n) (n & 0x7f) - -#define SOLO_VE_CH_INTL(ch) (0x0700+((ch)*4)) -#define SOLO_VE_CH_MOT(ch) (0x0740+((ch)*4)) -#define SOLO_VE_CH_QP(ch) (0x0780+((ch)*4)) -#define SOLO_VE_CH_QP_E(ch) (0x07C0+((ch)*4)) -#define SOLO_VE_CH_GOP(ch) (0x0800+((ch)*4)) -#define SOLO_VE_CH_GOP_E(ch) (0x0840+((ch)*4)) -#define SOLO_VE_CH_REF_BASE(ch) (0x0880+((ch)*4)) -#define SOLO_VE_CH_REF_BASE_E(ch) (0x08C0+((ch)*4)) - -#define SOLO_VE_MPEG4_QUE(n) (0x0A00+((n)*8)) -#define SOLO_VE_JPEG_QUE(n) (0x0A04+((n)*8)) - -#define SOLO_VD_CFG0 0x0900 -#define SOLO_VD_CFG_NO_WRITE_NO_WINDOW (1<<24) -#define SOLO_VD_CFG_BUSY_WIAT_CODE (1<<23) -#define SOLO_VD_CFG_BUSY_WIAT_REF (1<<22) -#define SOLO_VD_CFG_BUSY_WIAT_RES (1<<21) -#define SOLO_VD_CFG_BUSY_WIAT_MS (1<<20) -#define SOLO_VD_CFG_SINGLE_MODE (1<<18) -#define SOLO_VD_CFG_SCAL_MANUAL (1<<17) -#define SOLO_VD_CFG_USER_PAGE_CTRL (1<<16) -#define SOLO_VD_CFG_LITTLE_ENDIAN (1<<15) -#define SOLO_VD_CFG_START_FI (1<<14) -#define SOLO_VD_CFG_ERR_LOCK (1<<13) -#define SOLO_VD_CFG_ERR_INT_ENA (1<<12) -#define SOLO_VD_CFG_TIME_WIDTH(n) ((n)<<8) -#define SOLO_VD_CFG_DCT_INTERVAL(n) ((n)<<0) - -#define SOLO_VD_CFG1 0x0904 - -#define SOLO_VD_DEINTERLACE 0x0908 -#define SOLO_VD_DEINTERLACE_THRESHOLD(n) ((n)<<8) -#define SOLO_VD_DEINTERLACE_EDGE_VALUE(n) ((n)<<0) - -#define SOLO_VD_CODE_ADR 0x090C - -#define SOLO_VD_CTRL 0x0910 -#define SOLO_VD_OPER_ON (1<<31) -#define SOLO_VD_MAX_ITEM(n) ((n)<<0) - -#define SOLO_VD_STATUS0 0x0920 -#define SOLO_VD_STATUS0_INTR_ACK (1<<22) -#define SOLO_VD_STATUS0_INTR_EMPTY (1<<21) -#define SOLO_VD_STATUS0_INTR_ERR (1<<20) - -#define SOLO_VD_STATUS1 0x0924 - -#define SOLO_VD_IDX0 0x0930 -#define SOLO_VD_IDX_INTERLACE (1<<30) -#define SOLO_VD_IDX_CHANNEL(n) ((n)<<24) -#define SOLO_VD_IDX_SIZE(n) ((n)<<0) - -#define SOLO_VD_IDX1 0x0934 -#define SOLO_VD_IDX_SRC_SCALE(n) ((n)<<28) -#define SOLO_VD_IDX_WINDOW(n) ((n)<<24) -#define SOLO_VD_IDX_DEINTERLACE (1<<16) -#define SOLO_VD_IDX_H_BLOCK(n) ((n)<<8) -#define SOLO_VD_IDX_V_BLOCK(n) ((n)<<0) - -#define SOLO_VD_IDX2 0x0938 -#define SOLO_VD_IDX_REF_BASE_SIDE (1<<31) -#define SOLO_VD_IDX_REF_BASE(n) (((n)>>16)&0xffff) - -#define SOLO_VD_IDX3 0x093C -#define SOLO_VD_IDX_DISP_SCALE(n) ((n)<<28) -#define SOLO_VD_IDX_INTERLACE_WR (1<<27) -#define SOLO_VD_IDX_INTERPOL (1<<26) -#define SOLO_VD_IDX_HOR2X (1<<25) -#define SOLO_VD_IDX_OFFSET_X(n) ((n)<<12) -#define SOLO_VD_IDX_OFFSET_Y(n) ((n)<<0) - -#define SOLO_VD_IDX4 0x0940 -#define SOLO_VD_IDX_DEC_WR_PAGE(n) ((n)<<8) -#define SOLO_VD_IDX_DISP_RD_PAGE(n) ((n)<<0) - -#define SOLO_VD_WR_PAGE(n) (0x03F0 + ((n) * 4)) - - -#define SOLO_GPIO_CONFIG_0 0x0B00 -#define SOLO_GPIO_CONFIG_1 0x0B04 -#define SOLO_GPIO_DATA_OUT 0x0B08 -#define SOLO_GPIO_DATA_IN 0x0B0C -#define SOLO_GPIO_INT_ACK_STA 0x0B10 -#define SOLO_GPIO_INT_ENA 0x0B14 -#define SOLO_GPIO_INT_CFG_0 0x0B18 -#define SOLO_GPIO_INT_CFG_1 0x0B1C - - -#define SOLO_IIC_CFG 0x0B20 -#define SOLO_IIC_ENABLE (1<<8) -#define SOLO_IIC_PRESCALE(n) ((n)<<0) - -#define SOLO_IIC_CTRL 0x0B24 -#define SOLO_IIC_AUTO_CLEAR (1<<20) -#define SOLO_IIC_STATE_RX_ACK (1<<19) -#define SOLO_IIC_STATE_BUSY (1<<18) -#define SOLO_IIC_STATE_SIG_ERR (1<<17) -#define SOLO_IIC_STATE_TRNS (1<<16) -#define SOLO_IIC_CH_SET(n) ((n)<<5) -#define SOLO_IIC_ACK_EN (1<<4) -#define SOLO_IIC_START (1<<3) -#define SOLO_IIC_STOP (1<<2) -#define SOLO_IIC_READ (1<<1) -#define SOLO_IIC_WRITE (1<<0) - -#define SOLO_IIC_TXD 0x0B28 -#define SOLO_IIC_RXD 0x0B2C - -/* - * UART REGISTER - */ -#define SOLO_UART_CONTROL(n) (0x0BA0 + ((n)*0x20)) -#define SOLO_UART_CLK_DIV(n) ((n)<<24) -#define SOLO_MODEM_CTRL_EN (1<<20) -#define SOLO_PARITY_ERROR_DROP (1<<18) -#define SOLO_IRQ_ERR_EN (1<<17) -#define SOLO_IRQ_RX_EN (1<<16) -#define SOLO_IRQ_TX_EN (1<<15) -#define SOLO_RX_EN (1<<14) -#define SOLO_TX_EN (1<<13) -#define SOLO_UART_HALF_DUPLEX (1<<12) -#define SOLO_UART_LOOPBACK (1<<11) - -#define SOLO_BAUDRATE_230400 ((0<<9)|(0<<6)) -#define SOLO_BAUDRATE_115200 ((0<<9)|(1<<6)) -#define SOLO_BAUDRATE_57600 ((0<<9)|(2<<6)) -#define SOLO_BAUDRATE_38400 ((0<<9)|(3<<6)) -#define SOLO_BAUDRATE_19200 ((0<<9)|(4<<6)) -#define SOLO_BAUDRATE_9600 ((0<<9)|(5<<6)) -#define SOLO_BAUDRATE_4800 ((0<<9)|(6<<6)) -#define SOLO_BAUDRATE_2400 ((1<<9)|(6<<6)) -#define SOLO_BAUDRATE_1200 ((2<<9)|(6<<6)) -#define SOLO_BAUDRATE_300 ((3<<9)|(6<<6)) - -#define SOLO_UART_DATA_BIT_8 (3<<4) -#define SOLO_UART_DATA_BIT_7 (2<<4) -#define SOLO_UART_DATA_BIT_6 (1<<4) -#define SOLO_UART_DATA_BIT_5 (0<<4) - -#define SOLO_UART_STOP_BIT_1 (0<<2) -#define SOLO_UART_STOP_BIT_2 (1<<2) - -#define SOLO_UART_PARITY_NONE (0<<0) -#define SOLO_UART_PARITY_EVEN (2<<0) -#define SOLO_UART_PARITY_ODD (3<<0) - -#define SOLO_UART_STATUS(n) (0x0BA4 + ((n)*0x20)) -#define SOLO_UART_CTS (1<<15) -#define SOLO_UART_RX_BUSY (1<<14) -#define SOLO_UART_OVERRUN (1<<13) -#define SOLO_UART_FRAME_ERR (1<<12) -#define SOLO_UART_PARITY_ERR (1<<11) -#define SOLO_UART_TX_BUSY (1<<5) - -#define SOLO_UART_RX_BUFF_CNT(stat) (((stat)>>6) & 0x1f) -#define SOLO_UART_RX_BUFF_SIZE 8 -#define SOLO_UART_TX_BUFF_CNT(stat) (((stat)>>0) & 0x1f) -#define SOLO_UART_TX_BUFF_SIZE 8 - -#define SOLO_UART_TX_DATA(n) (0x0BA8 + ((n)*0x20)) -#define SOLO_UART_TX_DATA_PUSH (1<<8) -#define SOLO_UART_RX_DATA(n) (0x0BAC + ((n)*0x20)) -#define SOLO_UART_RX_DATA_POP (1<<8) - -#define SOLO_TIMER_CLOCK_NUM 0x0be0 -#define SOLO_TIMER_USEC 0x0be8 -#define SOLO_TIMER_SEC 0x0bec -#define SOLO_TIMER_USEC_LSB 0x0d20 /* 6110 Only */ - -#define SOLO_AUDIO_CONTROL 0x0D00 -#define SOLO_AUDIO_ENABLE (1<<31) -#define SOLO_AUDIO_MASTER_MODE (1<<30) -#define SOLO_AUDIO_I2S_MODE (1<<29) -#define SOLO_AUDIO_I2S_LR_SWAP (1<<27) -#define SOLO_AUDIO_I2S_8BIT (1<<26) -#define SOLO_AUDIO_I2S_MULTI(n) ((n)<<24) -#define SOLO_AUDIO_MIX_9TO0 (1<<23) -#define SOLO_AUDIO_DEC_9TO0_VOL(n) ((n)<<20) -#define SOLO_AUDIO_MIX_19TO10 (1<<19) -#define SOLO_AUDIO_DEC_19TO10_VOL(n) ((n)<<16) -#define SOLO_AUDIO_MODE(n) ((n)<<0) -#define SOLO_AUDIO_SAMPLE 0x0D04 -#define SOLO_AUDIO_EE_MODE_ON (1<<30) -#define SOLO_AUDIO_EE_ENC_CH(ch) ((ch)<<25) -#define SOLO_AUDIO_BITRATE(n) ((n)<<16) -#define SOLO_AUDIO_CLK_DIV(n) ((n)<<0) -#define SOLO_AUDIO_FDMA_INTR 0x0D08 -#define SOLO_AUDIO_FDMA_INTERVAL(n) ((n)<<19) -#define SOLO_AUDIO_INTR_ORDER(n) ((n)<<16) -#define SOLO_AUDIO_FDMA_BASE(n) ((n)<<0) -#define SOLO_AUDIO_EVOL_0 0x0D0C -#define SOLO_AUDIO_EVOL_1 0x0D10 -#define SOLO_AUDIO_EVOL(ch, value) ((value)<<((ch)%10)) -#define SOLO_AUDIO_STA 0x0D14 - -/* - * Watchdog configuration - */ -#define SOLO_WATCHDOG 0x0be4 -#define SOLO_WATCHDOG_SET(status, sec) (status << 8 | (sec & 0xff)) - -#endif /* __SOLO6X10_REGISTERS_H */ diff --git a/drivers/staging/media/solo6x10/solo6x10-tw28.c b/drivers/staging/media/solo6x10/solo6x10-tw28.c deleted file mode 100644 index 36daa1720b54..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-tw28.c +++ /dev/null @@ -1,874 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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/kernel.h> -#include <linux/delay.h> - -#include "solo6x10.h" -#include "solo6x10-tw28.h" - -#define DEFAULT_HDELAY_NTSC (32 - 8) -#define DEFAULT_HACTIVE_NTSC (720 + 16) -#define DEFAULT_VDELAY_NTSC (7 - 2) -#define DEFAULT_VACTIVE_NTSC (240 + 4) - -#define DEFAULT_HDELAY_PAL (32 + 4) -#define DEFAULT_HACTIVE_PAL (864-DEFAULT_HDELAY_PAL) -#define DEFAULT_VDELAY_PAL (6) -#define DEFAULT_VACTIVE_PAL (312-DEFAULT_VDELAY_PAL) - - -static const u8 tbl_tw2864_ntsc_template[] = { - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */ - 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */ - 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x20 */ - 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x30 */ - 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00, - 0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50, /* 0x80 */ - 0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00, - 0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05, /* 0x90 */ - 0x00, 0x28, 0x44, 0x44, 0xa0, 0x88, 0x5a, 0x01, - 0x08, 0x08, 0x08, 0x08, 0x1a, 0x1a, 0x1a, 0x1a, /* 0xa0 */ - 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44, - 0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef, /* 0xb0 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */ - 0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00, - 0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */ - 0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81, - 0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */ - 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, - 0x83, 0xb5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, /* 0xf0 */ - 0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00, -}; - -static const u8 tbl_tw2864_pal_template[] = { - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */ - 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f, - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */ - 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f, - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x20 */ - 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f, - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x30 */ - 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00, - 0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50, /* 0x80 */ - 0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00, - 0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05, /* 0x90 */ - 0x00, 0x28, 0x44, 0x44, 0xa0, 0x90, 0x5a, 0x01, - 0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x1a, 0x1a, 0x1a, /* 0xa0 */ - 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44, - 0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef, /* 0xb0 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */ - 0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00, - 0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */ - 0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81, - 0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */ - 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, - 0x83, 0xb5, 0x09, 0x00, 0xa0, 0x00, 0x01, 0x20, /* 0xf0 */ - 0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00, -}; - -static const u8 tbl_tw2865_ntsc_template[] = { - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */ - 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */ - 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x20 */ - 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0xf0, 0x70, 0x48, 0x80, 0x80, 0x00, 0x02, /* 0x30 */ - 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x90, 0x68, 0x00, 0x38, 0x80, 0x80, /* 0x40 */ - 0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43, - 0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03, /* 0x70 */ - 0xE9, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80, - 0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50, /* 0x80 */ - 0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00, - 0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05, /* 0x90 */ - 0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13, - 0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1B, 0x1A, /* 0xa0 */ - 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44, - 0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF, /* 0xb0 */ - 0xFF, 0xE7, 0xE9, 0xE9, 0xEB, 0xFF, 0xD6, 0xD8, - 0xD8, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */ - 0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80, - 0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31, /* 0xd0 */ - 0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81, - 0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */ - 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, - 0x83, 0xB5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, /* 0xf0 */ - 0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0, -}; - -static const u8 tbl_tw2865_pal_template[] = { - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */ - 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f, - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */ - 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f, - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x20 */ - 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f, - 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x30 */ - 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f, - 0x00, 0x94, 0x90, 0x48, 0x00, 0x38, 0x7F, 0x80, /* 0x40 */ - 0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43, - 0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03, /* 0x70 */ - 0xEA, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80, - 0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50, /* 0x80 */ - 0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00, - 0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05, /* 0x90 */ - 0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13, - 0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1A, 0x1A, /* 0xa0 */ - 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44, - 0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF, /* 0xb0 */ - 0xFF, 0xE7, 0xE9, 0xE9, 0xE9, 0xFF, 0xD7, 0xD8, - 0xD9, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */ - 0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80, - 0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31, /* 0xd0 */ - 0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81, - 0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */ - 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, - 0x83, 0xB5, 0x09, 0x00, 0xA0, 0x00, 0x01, 0x20, /* 0xf0 */ - 0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0, -}; - -#define is_tw286x(__solo, __id) (!(__solo->tw2815 & (1 << __id))) - -static u8 tw_readbyte(struct solo_dev *solo_dev, int chip_id, u8 tw6x_off, - u8 tw_off) -{ - if (is_tw286x(solo_dev, chip_id)) - return solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, - TW_CHIP_OFFSET_ADDR(chip_id), - tw6x_off); - else - return solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, - TW_CHIP_OFFSET_ADDR(chip_id), - tw_off); -} - -static void tw_writebyte(struct solo_dev *solo_dev, int chip_id, - u8 tw6x_off, u8 tw_off, u8 val) -{ - if (is_tw286x(solo_dev, chip_id)) - solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, - TW_CHIP_OFFSET_ADDR(chip_id), - tw6x_off, val); - else - solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, - TW_CHIP_OFFSET_ADDR(chip_id), - tw_off, val); -} - -static void tw_write_and_verify(struct solo_dev *solo_dev, u8 addr, u8 off, - u8 val) -{ - int i; - - for (i = 0; i < 5; i++) { - u8 rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, addr, off); - if (rval == val) - return; - - solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, addr, off, val); - msleep_interruptible(1); - } - -/* printk("solo6x10/tw28: Error writing register: %02x->%02x [%02x]\n", */ -/* addr, off, val); */ -} - -static int tw2865_setup(struct solo_dev *solo_dev, u8 dev_addr) -{ - u8 tbl_tw2865_common[256]; - int i; - - if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL) - memcpy(tbl_tw2865_common, tbl_tw2865_pal_template, - sizeof(tbl_tw2865_common)); - else - memcpy(tbl_tw2865_common, tbl_tw2865_ntsc_template, - sizeof(tbl_tw2865_common)); - - /* ALINK Mode */ - if (solo_dev->nr_chans == 4) { - tbl_tw2865_common[0xd2] = 0x01; - tbl_tw2865_common[0xcf] = 0x00; - } else if (solo_dev->nr_chans == 8) { - tbl_tw2865_common[0xd2] = 0x02; - if (dev_addr == TW_CHIP_OFFSET_ADDR(1)) - tbl_tw2865_common[0xcf] = 0x80; - } else if (solo_dev->nr_chans == 16) { - tbl_tw2865_common[0xd2] = 0x03; - if (dev_addr == TW_CHIP_OFFSET_ADDR(1)) - tbl_tw2865_common[0xcf] = 0x83; - else if (dev_addr == TW_CHIP_OFFSET_ADDR(2)) - tbl_tw2865_common[0xcf] = 0x83; - else if (dev_addr == TW_CHIP_OFFSET_ADDR(3)) - tbl_tw2865_common[0xcf] = 0x80; - } - - for (i = 0; i < 0xff; i++) { - /* Skip read only registers */ - switch (i) { - case 0xb8 ... 0xc1: - case 0xc4 ... 0xc7: - case 0xfd: - continue; - } - switch (i & ~0x30) { - case 0x00: - case 0x0c ... 0x0d: - continue; - } - - tw_write_and_verify(solo_dev, dev_addr, i, - tbl_tw2865_common[i]); - } - - return 0; -} - -static int tw2864_setup(struct solo_dev *solo_dev, u8 dev_addr) -{ - u8 tbl_tw2864_common[256]; - int i; - - if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL) - memcpy(tbl_tw2864_common, tbl_tw2864_pal_template, - sizeof(tbl_tw2864_common)); - else - memcpy(tbl_tw2864_common, tbl_tw2864_ntsc_template, - sizeof(tbl_tw2864_common)); - - if (solo_dev->tw2865 == 0) { - /* IRQ Mode */ - if (solo_dev->nr_chans == 4) { - tbl_tw2864_common[0xd2] = 0x01; - tbl_tw2864_common[0xcf] = 0x00; - } else if (solo_dev->nr_chans == 8) { - tbl_tw2864_common[0xd2] = 0x02; - if (dev_addr == TW_CHIP_OFFSET_ADDR(0)) - tbl_tw2864_common[0xcf] = 0x43; - else if (dev_addr == TW_CHIP_OFFSET_ADDR(1)) - tbl_tw2864_common[0xcf] = 0x40; - } else if (solo_dev->nr_chans == 16) { - tbl_tw2864_common[0xd2] = 0x03; - if (dev_addr == TW_CHIP_OFFSET_ADDR(0)) - tbl_tw2864_common[0xcf] = 0x43; - else if (dev_addr == TW_CHIP_OFFSET_ADDR(1)) - tbl_tw2864_common[0xcf] = 0x43; - else if (dev_addr == TW_CHIP_OFFSET_ADDR(2)) - tbl_tw2864_common[0xcf] = 0x43; - else if (dev_addr == TW_CHIP_OFFSET_ADDR(3)) - tbl_tw2864_common[0xcf] = 0x40; - } - } else { - /* ALINK Mode. Assumes that the first tw28xx is a - * 2865 and these are in cascade. */ - for (i = 0; i <= 4; i++) - tbl_tw2864_common[0x08 | i << 4] = 0x12; - - if (solo_dev->nr_chans == 8) { - tbl_tw2864_common[0xd2] = 0x02; - if (dev_addr == TW_CHIP_OFFSET_ADDR(1)) - tbl_tw2864_common[0xcf] = 0x80; - } else if (solo_dev->nr_chans == 16) { - tbl_tw2864_common[0xd2] = 0x03; - if (dev_addr == TW_CHIP_OFFSET_ADDR(1)) - tbl_tw2864_common[0xcf] = 0x83; - else if (dev_addr == TW_CHIP_OFFSET_ADDR(2)) - tbl_tw2864_common[0xcf] = 0x83; - else if (dev_addr == TW_CHIP_OFFSET_ADDR(3)) - tbl_tw2864_common[0xcf] = 0x80; - } - } - - for (i = 0; i < 0xff; i++) { - /* Skip read only registers */ - switch (i) { - case 0xb8 ... 0xc1: - case 0xfd: - continue; - } - switch (i & ~0x30) { - case 0x00: - case 0x0c: - case 0x0d: - continue; - } - - tw_write_and_verify(solo_dev, dev_addr, i, - tbl_tw2864_common[i]); - } - - return 0; -} - -static int tw2815_setup(struct solo_dev *solo_dev, u8 dev_addr) -{ - u8 tbl_ntsc_tw2815_common[] = { - 0x00, 0xc8, 0x20, 0xd0, 0x06, 0xf0, 0x08, 0x80, - 0x80, 0x80, 0x80, 0x02, 0x06, 0x00, 0x11, - }; - - u8 tbl_pal_tw2815_common[] = { - 0x00, 0x88, 0x20, 0xd0, 0x05, 0x20, 0x28, 0x80, - 0x80, 0x80, 0x80, 0x82, 0x06, 0x00, 0x11, - }; - - u8 tbl_tw2815_sfr[] = { - 0x00, 0x00, 0x00, 0xc0, 0x45, 0xa0, 0xd0, 0x2f, /* 0x00 */ - 0x64, 0x80, 0x80, 0x82, 0x82, 0x00, 0x00, 0x00, - 0x00, 0x0f, 0x05, 0x00, 0x00, 0x80, 0x06, 0x00, /* 0x10 */ - 0x00, 0x00, 0x00, 0xff, 0x8f, 0x00, 0x00, 0x00, - 0x88, 0x88, 0xc0, 0x00, 0x20, 0x64, 0xa8, 0xec, /* 0x20 */ - 0x31, 0x75, 0xb9, 0xfd, 0x00, 0x00, 0x88, 0x88, - 0x88, 0x11, 0x00, 0x88, 0x88, 0x00, /* 0x30 */ - }; - u8 *tbl_tw2815_common; - int i; - int ch; - - tbl_ntsc_tw2815_common[0x06] = 0; - - /* Horizontal Delay Control */ - tbl_ntsc_tw2815_common[0x02] = DEFAULT_HDELAY_NTSC & 0xff; - tbl_ntsc_tw2815_common[0x06] |= 0x03 & (DEFAULT_HDELAY_NTSC >> 8); - - /* Horizontal Active Control */ - tbl_ntsc_tw2815_common[0x03] = DEFAULT_HACTIVE_NTSC & 0xff; - tbl_ntsc_tw2815_common[0x06] |= - ((0x03 & (DEFAULT_HACTIVE_NTSC >> 8)) << 2); - - /* Vertical Delay Control */ - tbl_ntsc_tw2815_common[0x04] = DEFAULT_VDELAY_NTSC & 0xff; - tbl_ntsc_tw2815_common[0x06] |= - ((0x01 & (DEFAULT_VDELAY_NTSC >> 8)) << 4); - - /* Vertical Active Control */ - tbl_ntsc_tw2815_common[0x05] = DEFAULT_VACTIVE_NTSC & 0xff; - tbl_ntsc_tw2815_common[0x06] |= - ((0x01 & (DEFAULT_VACTIVE_NTSC >> 8)) << 5); - - tbl_pal_tw2815_common[0x06] = 0; - - /* Horizontal Delay Control */ - tbl_pal_tw2815_common[0x02] = DEFAULT_HDELAY_PAL & 0xff; - tbl_pal_tw2815_common[0x06] |= 0x03 & (DEFAULT_HDELAY_PAL >> 8); - - /* Horizontal Active Control */ - tbl_pal_tw2815_common[0x03] = DEFAULT_HACTIVE_PAL & 0xff; - tbl_pal_tw2815_common[0x06] |= - ((0x03 & (DEFAULT_HACTIVE_PAL >> 8)) << 2); - - /* Vertical Delay Control */ - tbl_pal_tw2815_common[0x04] = DEFAULT_VDELAY_PAL & 0xff; - tbl_pal_tw2815_common[0x06] |= - ((0x01 & (DEFAULT_VDELAY_PAL >> 8)) << 4); - - /* Vertical Active Control */ - tbl_pal_tw2815_common[0x05] = DEFAULT_VACTIVE_PAL & 0xff; - tbl_pal_tw2815_common[0x06] |= - ((0x01 & (DEFAULT_VACTIVE_PAL >> 8)) << 5); - - tbl_tw2815_common = - (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) ? - tbl_ntsc_tw2815_common : tbl_pal_tw2815_common; - - /* Dual ITU-R BT.656 format */ - tbl_tw2815_common[0x0d] |= 0x04; - - /* Audio configuration */ - tbl_tw2815_sfr[0x62 - 0x40] &= ~(3 << 6); - - if (solo_dev->nr_chans == 4) { - tbl_tw2815_sfr[0x63 - 0x40] |= 1; - tbl_tw2815_sfr[0x62 - 0x40] |= 3 << 6; - } else if (solo_dev->nr_chans == 8) { - tbl_tw2815_sfr[0x63 - 0x40] |= 2; - if (dev_addr == TW_CHIP_OFFSET_ADDR(0)) - tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6; - else if (dev_addr == TW_CHIP_OFFSET_ADDR(1)) - tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6; - } else if (solo_dev->nr_chans == 16) { - tbl_tw2815_sfr[0x63 - 0x40] |= 3; - if (dev_addr == TW_CHIP_OFFSET_ADDR(0)) - tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6; - else if (dev_addr == TW_CHIP_OFFSET_ADDR(1)) - tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6; - else if (dev_addr == TW_CHIP_OFFSET_ADDR(2)) - tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6; - else if (dev_addr == TW_CHIP_OFFSET_ADDR(3)) - tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6; - } - - /* Output mode of R_ADATM pin (0 mixing, 1 record) */ - /* tbl_tw2815_sfr[0x63 - 0x40] |= 0 << 2; */ - - /* 8KHz, used to be 16KHz, but changed for remote client compat */ - tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 2; - tbl_tw2815_sfr[0x6c - 0x40] |= 0 << 2; - - /* Playback of right channel */ - tbl_tw2815_sfr[0x6c - 0x40] |= 1 << 5; - - /* Reserved value (XXX ??) */ - tbl_tw2815_sfr[0x5c - 0x40] |= 1 << 5; - - /* Analog output gain and mix ratio playback on full */ - tbl_tw2815_sfr[0x70 - 0x40] |= 0xff; - /* Select playback audio and mute all except */ - tbl_tw2815_sfr[0x71 - 0x40] |= 0x10; - tbl_tw2815_sfr[0x6d - 0x40] |= 0x0f; - - /* End of audio configuration */ - - for (ch = 0; ch < 4; ch++) { - tbl_tw2815_common[0x0d] &= ~3; - switch (ch) { - case 0: - tbl_tw2815_common[0x0d] |= 0x21; - break; - case 1: - tbl_tw2815_common[0x0d] |= 0x20; - break; - case 2: - tbl_tw2815_common[0x0d] |= 0x23; - break; - case 3: - tbl_tw2815_common[0x0d] |= 0x22; - break; - } - - for (i = 0; i < 0x0f; i++) { - if (i == 0x00) - continue; /* read-only */ - solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, - dev_addr, (ch * 0x10) + i, - tbl_tw2815_common[i]); - } - } - - for (i = 0x40; i < 0x76; i++) { - /* Skip read-only and nop registers */ - if (i == 0x40 || i == 0x59 || i == 0x5a || - i == 0x5d || i == 0x5e || i == 0x5f) - continue; - - solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, dev_addr, i, - tbl_tw2815_sfr[i - 0x40]); - } - - return 0; -} - -#define FIRST_ACTIVE_LINE 0x0008 -#define LAST_ACTIVE_LINE 0x0102 - -static void saa712x_write_regs(struct solo_dev *dev, const uint8_t *vals, - int start, int n) -{ - for (; start < n; start++, vals++) { - /* Skip read-only registers */ - switch (start) { - /* case 0x00 ... 0x25: */ - case 0x2e ... 0x37: - case 0x60: - case 0x7d: - continue; - } - solo_i2c_writebyte(dev, SOLO_I2C_SAA, 0x46, start, *vals); - } -} - -#define SAA712x_reg7c (0x80 | ((LAST_ACTIVE_LINE & 0x100) >> 2) \ - | ((FIRST_ACTIVE_LINE & 0x100) >> 4)) - -static void saa712x_setup(struct solo_dev *dev) -{ - const int reg_start = 0x26; - const uint8_t saa7128_regs_ntsc[] = { - /* :0x26 */ - 0x0d, 0x00, - /* :0x28 */ - 0x59, 0x1d, 0x75, 0x3f, 0x06, 0x3f, - /* :0x2e XXX: read-only */ - 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* :0x38 */ - 0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, - /* :0x40 */ - 0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18, - 0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f, - /* :0x50 */ - 0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06, - 0x02, 0x80, 0x71, 0x77, 0xa7, 0x67, 0x66, 0x2e, - /* :0x60 */ - 0x7b, 0x11, 0x4f, 0x1f, 0x7c, 0xf0, 0x21, 0x77, - 0x41, 0x88, 0x41, 0x52, 0xed, 0x10, 0x10, 0x00, - /* :0x70 */ - 0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00, - 0x00, 0x00, FIRST_ACTIVE_LINE, LAST_ACTIVE_LINE & 0xff, - SAA712x_reg7c, 0x00, 0xff, 0xff, - }, saa7128_regs_pal[] = { - /* :0x26 */ - 0x0d, 0x00, - /* :0x28 */ - 0xe1, 0x1d, 0x75, 0x3f, 0x06, 0x3f, - /* :0x2e XXX: read-only */ - 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* :0x38 */ - 0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, - /* :0x40 */ - 0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18, - 0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f, - /* :0x50 */ - 0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06, - 0x02, 0x80, 0x0f, 0x77, 0xa7, 0x67, 0x66, 0x2e, - /* :0x60 */ - 0x7b, 0x02, 0x35, 0xcb, 0x8a, 0x09, 0x2a, 0x77, - 0x41, 0x88, 0x41, 0x52, 0xf1, 0x10, 0x20, 0x00, - /* :0x70 */ - 0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x12, 0x30, - SAA712x_reg7c | 0x40, 0x00, 0xff, 0xff, - }; - - if (dev->video_type == SOLO_VO_FMT_TYPE_PAL) - saa712x_write_regs(dev, saa7128_regs_pal, reg_start, - sizeof(saa7128_regs_pal)); - else - saa712x_write_regs(dev, saa7128_regs_ntsc, reg_start, - sizeof(saa7128_regs_ntsc)); -} - -int solo_tw28_init(struct solo_dev *solo_dev) -{ - int i; - u8 value; - - solo_dev->tw28_cnt = 0; - - /* Detect techwell chip type(s) */ - for (i = 0; i < solo_dev->nr_chans / 4; i++) { - value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, - TW_CHIP_OFFSET_ADDR(i), 0xFF); - - switch (value >> 3) { - case 0x18: - solo_dev->tw2865 |= 1 << i; - solo_dev->tw28_cnt++; - break; - case 0x0c: - solo_dev->tw2864 |= 1 << i; - solo_dev->tw28_cnt++; - break; - default: - value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, - TW_CHIP_OFFSET_ADDR(i), - 0x59); - if ((value >> 3) == 0x04) { - solo_dev->tw2815 |= 1 << i; - solo_dev->tw28_cnt++; - } - } - } - - if (solo_dev->tw28_cnt != (solo_dev->nr_chans >> 2)) { - dev_err(&solo_dev->pdev->dev, - "Could not initialize any techwell chips\n"); - return -EINVAL; - } - - saa712x_setup(solo_dev); - - for (i = 0; i < solo_dev->tw28_cnt; i++) { - if ((solo_dev->tw2865 & (1 << i))) - tw2865_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i)); - else if ((solo_dev->tw2864 & (1 << i))) - tw2864_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i)); - else - tw2815_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i)); - } - - return 0; -} - -/* - * We accessed the video status signal in the Techwell chip through - * iic/i2c because the video status reported by register REG_VI_STATUS1 - * (address 0x012C) of the SOLO6010 chip doesn't give the correct video - * status signal values. - */ -int tw28_get_video_status(struct solo_dev *solo_dev, u8 ch) -{ - u8 val, chip_num; - - /* Get the right chip and on-chip channel */ - chip_num = ch / 4; - ch %= 4; - - val = tw_readbyte(solo_dev, chip_num, TW286x_AV_STAT_ADDR, - TW_AV_STAT_ADDR) & 0x0f; - - return val & (1 << ch) ? 1 : 0; -} - -#if 0 -/* Status of audio from up to 4 techwell chips are combined into 1 variable. - * See techwell datasheet for details. */ -u16 tw28_get_audio_status(struct solo_dev *solo_dev) -{ - u8 val; - u16 status = 0; - int i; - - for (i = 0; i < solo_dev->tw28_cnt; i++) { - val = (tw_readbyte(solo_dev, i, TW286x_AV_STAT_ADDR, - TW_AV_STAT_ADDR) & 0xf0) >> 4; - status |= val << (i * 4); - } - - return status; -} -#endif - -bool tw28_has_sharpness(struct solo_dev *solo_dev, u8 ch) -{ - return is_tw286x(solo_dev, ch / 4); -} - -int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, - s32 val) -{ - char sval; - u8 chip_num; - - /* Get the right chip and on-chip channel */ - chip_num = ch / 4; - ch %= 4; - - if (val > 255 || val < 0) - return -ERANGE; - - switch (ctrl) { - case V4L2_CID_SHARPNESS: - /* Only 286x has sharpness */ - if (is_tw286x(solo_dev, chip_num)) { - u8 v = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, - TW_CHIP_OFFSET_ADDR(chip_num), - TW286x_SHARPNESS(chip_num)); - v &= 0xf0; - v |= val; - solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, - TW_CHIP_OFFSET_ADDR(chip_num), - TW286x_SHARPNESS(chip_num), v); - } else { - return -EINVAL; - } - break; - - case V4L2_CID_HUE: - if (is_tw286x(solo_dev, chip_num)) - sval = val - 128; - else - sval = (char)val; - tw_writebyte(solo_dev, chip_num, TW286x_HUE_ADDR(ch), - TW_HUE_ADDR(ch), sval); - - break; - - case V4L2_CID_SATURATION: - /* 286x chips have a U and V component for saturation */ - if (is_tw286x(solo_dev, chip_num)) { - solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, - TW_CHIP_OFFSET_ADDR(chip_num), - TW286x_SATURATIONU_ADDR(ch), val); - } - tw_writebyte(solo_dev, chip_num, TW286x_SATURATIONV_ADDR(ch), - TW_SATURATION_ADDR(ch), val); - - break; - - case V4L2_CID_CONTRAST: - tw_writebyte(solo_dev, chip_num, TW286x_CONTRAST_ADDR(ch), - TW_CONTRAST_ADDR(ch), val); - break; - - case V4L2_CID_BRIGHTNESS: - if (is_tw286x(solo_dev, chip_num)) - sval = val - 128; - else - sval = (char)val; - tw_writebyte(solo_dev, chip_num, TW286x_BRIGHTNESS_ADDR(ch), - TW_BRIGHTNESS_ADDR(ch), sval); - - break; - default: - return -EINVAL; - } - - return 0; -} - -int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, - s32 *val) -{ - u8 rval, chip_num; - - /* Get the right chip and on-chip channel */ - chip_num = ch / 4; - ch %= 4; - - switch (ctrl) { - case V4L2_CID_SHARPNESS: - /* Only 286x has sharpness */ - if (is_tw286x(solo_dev, chip_num)) { - rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, - TW_CHIP_OFFSET_ADDR(chip_num), - TW286x_SHARPNESS(chip_num)); - *val = rval & 0x0f; - } else - *val = 0; - break; - case V4L2_CID_HUE: - rval = tw_readbyte(solo_dev, chip_num, TW286x_HUE_ADDR(ch), - TW_HUE_ADDR(ch)); - if (is_tw286x(solo_dev, chip_num)) - *val = (s32)((char)rval) + 128; - else - *val = rval; - break; - case V4L2_CID_SATURATION: - *val = tw_readbyte(solo_dev, chip_num, - TW286x_SATURATIONU_ADDR(ch), - TW_SATURATION_ADDR(ch)); - break; - case V4L2_CID_CONTRAST: - *val = tw_readbyte(solo_dev, chip_num, - TW286x_CONTRAST_ADDR(ch), - TW_CONTRAST_ADDR(ch)); - break; - case V4L2_CID_BRIGHTNESS: - rval = tw_readbyte(solo_dev, chip_num, - TW286x_BRIGHTNESS_ADDR(ch), - TW_BRIGHTNESS_ADDR(ch)); - if (is_tw286x(solo_dev, chip_num)) - *val = (s32)((char)rval) + 128; - else - *val = rval; - break; - default: - return -EINVAL; - } - - return 0; -} - -#if 0 -/* - * For audio output volume, the output channel is only 1. In this case we - * don't need to offset TW_CHIP_OFFSET_ADDR. The TW_CHIP_OFFSET_ADDR used - * is the base address of the techwell chip. - */ -void tw2815_Set_AudioOutVol(struct solo_dev *solo_dev, unsigned int u_val) -{ - unsigned int val; - unsigned int chip_num; - - chip_num = (solo_dev->nr_chans - 1) / 4; - - val = tw_readbyte(solo_dev, chip_num, TW286x_AUDIO_OUTPUT_VOL_ADDR, - TW_AUDIO_OUTPUT_VOL_ADDR); - - u_val = (val & 0x0f) | (u_val << 4); - - tw_writebyte(solo_dev, chip_num, TW286x_AUDIO_OUTPUT_VOL_ADDR, - TW_AUDIO_OUTPUT_VOL_ADDR, u_val); -} -#endif - -u8 tw28_get_audio_gain(struct solo_dev *solo_dev, u8 ch) -{ - u8 val; - u8 chip_num; - - /* Get the right chip and on-chip channel */ - chip_num = ch / 4; - ch %= 4; - - val = tw_readbyte(solo_dev, chip_num, - TW286x_AUDIO_INPUT_GAIN_ADDR(ch), - TW_AUDIO_INPUT_GAIN_ADDR(ch)); - - return (ch % 2) ? (val >> 4) : (val & 0x0f); -} - -void tw28_set_audio_gain(struct solo_dev *solo_dev, u8 ch, u8 val) -{ - u8 old_val; - u8 chip_num; - - /* Get the right chip and on-chip channel */ - chip_num = ch / 4; - ch %= 4; - - old_val = tw_readbyte(solo_dev, chip_num, - TW286x_AUDIO_INPUT_GAIN_ADDR(ch), - TW_AUDIO_INPUT_GAIN_ADDR(ch)); - - val = (old_val & ((ch % 2) ? 0x0f : 0xf0)) | - ((ch % 2) ? (val << 4) : val); - - tw_writebyte(solo_dev, chip_num, TW286x_AUDIO_INPUT_GAIN_ADDR(ch), - TW_AUDIO_INPUT_GAIN_ADDR(ch), val); -} diff --git a/drivers/staging/media/solo6x10/solo6x10-tw28.h b/drivers/staging/media/solo6x10/solo6x10-tw28.h deleted file mode 100644 index 1a02c87d4cf0..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-tw28.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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 __SOLO6X10_TW28_H -#define __SOLO6X10_TW28_H - -#include "solo6x10.h" - -#define TW_NUM_CHIP 4 -#define TW_BASE_ADDR 0x28 -#define TW_CHIP_OFFSET_ADDR(n) (TW_BASE_ADDR + (n)) - -/* tw2815 */ -#define TW_AV_STAT_ADDR 0x5a -#define TW_HUE_ADDR(n) (0x07 | ((n) << 4)) -#define TW_SATURATION_ADDR(n) (0x08 | ((n) << 4)) -#define TW_CONTRAST_ADDR(n) (0x09 | ((n) << 4)) -#define TW_BRIGHTNESS_ADDR(n) (0x0a | ((n) << 4)) -#define TW_AUDIO_OUTPUT_VOL_ADDR 0x70 -#define TW_AUDIO_INPUT_GAIN_ADDR(n) (0x60 + ((n > 1) ? 1 : 0)) - -/* tw286x */ -#define TW286x_AV_STAT_ADDR 0xfd -#define TW286x_HUE_ADDR(n) (0x06 | ((n) << 4)) -#define TW286x_SATURATIONU_ADDR(n) (0x04 | ((n) << 4)) -#define TW286x_SATURATIONV_ADDR(n) (0x05 | ((n) << 4)) -#define TW286x_CONTRAST_ADDR(n) (0x02 | ((n) << 4)) -#define TW286x_BRIGHTNESS_ADDR(n) (0x01 | ((n) << 4)) -#define TW286x_SHARPNESS(n) (0x03 | ((n) << 4)) -#define TW286x_AUDIO_OUTPUT_VOL_ADDR 0xdf -#define TW286x_AUDIO_INPUT_GAIN_ADDR(n) (0xD0 + ((n > 1) ? 1 : 0)) - -int solo_tw28_init(struct solo_dev *solo_dev); - -int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val); -int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 *val); -bool tw28_has_sharpness(struct solo_dev *solo_dev, u8 ch); - -u8 tw28_get_audio_gain(struct solo_dev *solo_dev, u8 ch); -void tw28_set_audio_gain(struct solo_dev *solo_dev, u8 ch, u8 val); -int tw28_get_video_status(struct solo_dev *solo_dev, u8 ch); - -#if 0 -unsigned int tw2815_get_audio_status(struct SOLO *solo); -void tw2815_Set_AudioOutVol(struct SOLO *solo, unsigned int u_val); -#endif - -#endif /* __SOLO6X10_TW28_H */ diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c deleted file mode 100644 index b8ff113c20f4..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c +++ /dev/null @@ -1,1414 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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/kernel.h> -#include <linux/module.h> -#include <linux/kthread.h> -#include <linux/freezer.h> - -#include <media/v4l2-ioctl.h> -#include <media/v4l2-common.h> -#include <media/v4l2-event.h> -#include <media/videobuf2-dma-sg.h> - -#include "solo6x10.h" -#include "solo6x10-tw28.h" -#include "solo6x10-jpeg.h" - -#define MIN_VID_BUFFERS 2 -#define FRAME_BUF_SIZE (196 * 1024) -#define MP4_QS 16 -#define DMA_ALIGN 4096 - -/* 6010 M4V */ -static unsigned char vop_6010_ntsc_d1[] = { - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, - 0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40, - 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04, - 0x1f, 0x4c, 0x58, 0x10, 0xf0, 0x71, 0x18, 0x3f, -}; - -static unsigned char vop_6010_ntsc_cif[] = { - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, - 0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40, - 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04, - 0x1f, 0x4c, 0x2c, 0x10, 0x78, 0x51, 0x18, 0x3f, -}; - -static unsigned char vop_6010_pal_d1[] = { - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, - 0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40, - 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04, - 0x1f, 0x4c, 0x58, 0x11, 0x20, 0x71, 0x18, 0x3f, -}; - -static unsigned char vop_6010_pal_cif[] = { - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, - 0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40, - 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04, - 0x1f, 0x4c, 0x2c, 0x10, 0x90, 0x51, 0x18, 0x3f, -}; - -/* 6110 h.264 */ -static unsigned char vop_6110_ntsc_d1[] = { - 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e, - 0x9a, 0x74, 0x05, 0x81, 0xec, 0x80, 0x00, 0x00, - 0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, -}; - -static unsigned char vop_6110_ntsc_cif[] = { - 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e, - 0x9a, 0x74, 0x0b, 0x0f, 0xc8, 0x00, 0x00, 0x00, - 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00, -}; - -static unsigned char vop_6110_pal_d1[] = { - 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e, - 0x9a, 0x74, 0x05, 0x80, 0x93, 0x20, 0x00, 0x00, - 0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, -}; - -static unsigned char vop_6110_pal_cif[] = { - 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e, - 0x9a, 0x74, 0x0b, 0x04, 0xb2, 0x00, 0x00, 0x00, - 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00, -}; - -typedef __le32 vop_header[16]; - -struct solo_enc_buf { - enum solo_enc_types type; - const vop_header *vh; - int motion; -}; - -static int solo_is_motion_on(struct solo_enc_dev *solo_enc) -{ - struct solo_dev *solo_dev = solo_enc->solo_dev; - - return (solo_dev->motion_mask >> solo_enc->ch) & 1; -} - -static int solo_motion_detected(struct solo_enc_dev *solo_enc) -{ - struct solo_dev *solo_dev = solo_enc->solo_dev; - unsigned long flags; - u32 ch_mask = 1 << solo_enc->ch; - int ret = 0; - - spin_lock_irqsave(&solo_enc->motion_lock, flags); - if (solo_reg_read(solo_dev, SOLO_VI_MOT_STATUS) & ch_mask) { - solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, ch_mask); - ret = 1; - } - spin_unlock_irqrestore(&solo_enc->motion_lock, flags); - - return ret; -} - -static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on) -{ - struct solo_dev *solo_dev = solo_enc->solo_dev; - u32 mask = 1 << solo_enc->ch; - unsigned long flags; - - spin_lock_irqsave(&solo_enc->motion_lock, flags); - - if (on) - solo_dev->motion_mask |= mask; - else - solo_dev->motion_mask &= ~mask; - - solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, mask); - - solo_reg_write(solo_dev, SOLO_VI_MOT_ADR, - SOLO_VI_MOTION_EN(solo_dev->motion_mask) | - (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16)); - - spin_unlock_irqrestore(&solo_enc->motion_lock, flags); -} - -void solo_update_mode(struct solo_enc_dev *solo_enc) -{ - struct solo_dev *solo_dev = solo_enc->solo_dev; - int vop_len; - unsigned char *vop; - - solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0; - solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1); - - if (solo_enc->mode == SOLO_ENC_MODE_CIF) { - solo_enc->width = solo_dev->video_hsize >> 1; - solo_enc->height = solo_dev->video_vsize; - if (solo_dev->type == SOLO_DEV_6110) { - if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) { - vop = vop_6110_ntsc_cif; - vop_len = sizeof(vop_6110_ntsc_cif); - } else { - vop = vop_6110_pal_cif; - vop_len = sizeof(vop_6110_pal_cif); - } - } else { - if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) { - vop = vop_6010_ntsc_cif; - vop_len = sizeof(vop_6010_ntsc_cif); - } else { - vop = vop_6010_pal_cif; - vop_len = sizeof(vop_6010_pal_cif); - } - } - } else { - solo_enc->width = solo_dev->video_hsize; - solo_enc->height = solo_dev->video_vsize << 1; - solo_enc->bw_weight <<= 2; - if (solo_dev->type == SOLO_DEV_6110) { - if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) { - vop = vop_6110_ntsc_d1; - vop_len = sizeof(vop_6110_ntsc_d1); - } else { - vop = vop_6110_pal_d1; - vop_len = sizeof(vop_6110_pal_d1); - } - } else { - if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) { - vop = vop_6010_ntsc_d1; - vop_len = sizeof(vop_6010_ntsc_d1); - } else { - vop = vop_6010_pal_d1; - vop_len = sizeof(vop_6010_pal_d1); - } - } - } - - memcpy(solo_enc->vop, vop, vop_len); - - /* Some fixups for 6010/M4V */ - if (solo_dev->type == SOLO_DEV_6010) { - u16 fps = solo_dev->fps * 1000; - u16 interval = solo_enc->interval * 1000; - - vop = solo_enc->vop; - - /* Frame rate and interval */ - vop[22] = fps >> 4; - vop[23] = ((fps << 4) & 0xf0) | 0x0c - | ((interval >> 13) & 0x3); - vop[24] = (interval >> 5) & 0xff; - vop[25] = ((interval << 3) & 0xf8) | 0x04; - } - - solo_enc->vop_len = vop_len; - - /* Now handle the jpeg header */ - vop = solo_enc->jpeg_header; - vop[SOF0_START + 5] = 0xff & (solo_enc->height >> 8); - vop[SOF0_START + 6] = 0xff & solo_enc->height; - vop[SOF0_START + 7] = 0xff & (solo_enc->width >> 8); - vop[SOF0_START + 8] = 0xff & solo_enc->width; - - memcpy(vop + DQT_START, - jpeg_dqt[solo_g_jpeg_qp(solo_dev, solo_enc->ch)], DQT_LEN); -} - -static int solo_enc_on(struct solo_enc_dev *solo_enc) -{ - u8 ch = solo_enc->ch; - struct solo_dev *solo_dev = solo_enc->solo_dev; - u8 interval; - - solo_update_mode(solo_enc); - - /* Make sure to do a bandwidth check */ - if (solo_enc->bw_weight > solo_dev->enc_bw_remain) - return -EBUSY; - solo_enc->sequence = 0; - solo_dev->enc_bw_remain -= solo_enc->bw_weight; - - if (solo_enc->type == SOLO_ENC_TYPE_EXT) - solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1); - - /* Disable all encoding for this channel */ - solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0); - - /* Common for both std and ext encoding */ - solo_reg_write(solo_dev, SOLO_VE_CH_INTL(ch), - solo_enc->interlaced ? 1 : 0); - - if (solo_enc->interlaced) - interval = solo_enc->interval - 1; - else - interval = solo_enc->interval; - - /* Standard encoding only */ - solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), solo_enc->gop); - solo_reg_write(solo_dev, SOLO_VE_CH_QP(ch), solo_enc->qp); - solo_reg_write(solo_dev, SOLO_CAP_CH_INTV(ch), interval); - - /* Extended encoding only */ - solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(ch), solo_enc->gop); - solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(ch), solo_enc->qp); - solo_reg_write(solo_dev, SOLO_CAP_CH_INTV_E(ch), interval); - - /* Enables the standard encoder */ - solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), solo_enc->mode); - - return 0; -} - -static void solo_enc_off(struct solo_enc_dev *solo_enc) -{ - struct solo_dev *solo_dev = solo_enc->solo_dev; - - solo_dev->enc_bw_remain += solo_enc->bw_weight; - - solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0); - solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0); -} - -static int enc_get_mpeg_dma(struct solo_dev *solo_dev, dma_addr_t dma, - unsigned int off, unsigned int size) -{ - int ret; - - if (off > SOLO_MP4E_EXT_SIZE(solo_dev)) - return -EINVAL; - - /* Single shot */ - if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) { - return solo_p2m_dma_t(solo_dev, 0, dma, - SOLO_MP4E_EXT_ADDR(solo_dev) + off, size, - 0, 0); - } - - /* Buffer wrap */ - ret = solo_p2m_dma_t(solo_dev, 0, dma, - SOLO_MP4E_EXT_ADDR(solo_dev) + off, - SOLO_MP4E_EXT_SIZE(solo_dev) - off, 0, 0); - - if (!ret) { - ret = solo_p2m_dma_t(solo_dev, 0, - dma + SOLO_MP4E_EXT_SIZE(solo_dev) - off, - SOLO_MP4E_EXT_ADDR(solo_dev), - size + off - SOLO_MP4E_EXT_SIZE(solo_dev), 0, 0); - } - - return ret; -} - -/* Build a descriptor queue out of an SG list and send it to the P2M for - * processing. */ -static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip, - struct sg_table *vbuf, int off, int size, - unsigned int base, unsigned int base_size) -{ - struct solo_dev *solo_dev = solo_enc->solo_dev; - struct scatterlist *sg; - int i; - int ret; - - if (WARN_ON_ONCE(size > FRAME_BUF_SIZE)) - return -EINVAL; - - solo_enc->desc_count = 1; - - for_each_sg(vbuf->sgl, sg, vbuf->nents, i) { - struct solo_p2m_desc *desc; - dma_addr_t dma; - int len; - int left = base_size - off; - - desc = &solo_enc->desc_items[solo_enc->desc_count++]; - dma = sg_dma_address(sg); - len = sg_dma_len(sg); - - /* We assume this is smaller than the scatter size */ - BUG_ON(skip >= len); - if (skip) { - len -= skip; - dma += skip; - size -= skip; - skip = 0; - } - - len = min(len, size); - - if (len <= left) { - /* Single descriptor */ - solo_p2m_fill_desc(desc, 0, dma, base + off, - len, 0, 0); - } else { - /* Buffer wrap */ - /* XXX: Do these as separate DMA requests, to avoid - timeout errors triggered by awkwardly sized - descriptors. See - <https://github.com/bluecherrydvr/solo6x10/issues/8> - */ - ret = solo_p2m_dma_t(solo_dev, 0, dma, base + off, - left, 0, 0); - if (ret) - return ret; - - ret = solo_p2m_dma_t(solo_dev, 0, dma + left, base, - len - left, 0, 0); - if (ret) - return ret; - - solo_enc->desc_count--; - } - - size -= len; - if (size <= 0) - break; - - off += len; - if (off >= base_size) - off -= base_size; - - /* Because we may use two descriptors per loop */ - if (solo_enc->desc_count >= (solo_enc->desc_nelts - 1)) { - ret = solo_p2m_dma_desc(solo_dev, solo_enc->desc_items, - solo_enc->desc_dma, - solo_enc->desc_count - 1); - if (ret) - return ret; - solo_enc->desc_count = 1; - } - } - - if (solo_enc->desc_count <= 1) - return 0; - - return solo_p2m_dma_desc(solo_dev, solo_enc->desc_items, - solo_enc->desc_dma, solo_enc->desc_count - 1); -} - -/* Extract values from VOP header - VE_STATUSxx */ -static inline int vop_interlaced(const vop_header *vh) -{ - return (__le32_to_cpu((*vh)[0]) >> 30) & 1; -} - -static inline u8 vop_channel(const vop_header *vh) -{ - return (__le32_to_cpu((*vh)[0]) >> 24) & 0x1F; -} - -static inline u8 vop_type(const vop_header *vh) -{ - return (__le32_to_cpu((*vh)[0]) >> 22) & 3; -} - -static inline u32 vop_mpeg_size(const vop_header *vh) -{ - return __le32_to_cpu((*vh)[0]) & 0xFFFFF; -} - -static inline u8 vop_hsize(const vop_header *vh) -{ - return (__le32_to_cpu((*vh)[1]) >> 8) & 0xFF; -} - -static inline u8 vop_vsize(const vop_header *vh) -{ - return __le32_to_cpu((*vh)[1]) & 0xFF; -} - -static inline u32 vop_mpeg_offset(const vop_header *vh) -{ - return __le32_to_cpu((*vh)[2]); -} - -static inline u32 vop_jpeg_offset(const vop_header *vh) -{ - return __le32_to_cpu((*vh)[3]); -} - -static inline u32 vop_jpeg_size(const vop_header *vh) -{ - return __le32_to_cpu((*vh)[4]) & 0xFFFFF; -} - -static inline u32 vop_sec(const vop_header *vh) -{ - return __le32_to_cpu((*vh)[5]); -} - -static inline u32 vop_usec(const vop_header *vh) -{ - return __le32_to_cpu((*vh)[6]); -} - -static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, - struct vb2_buffer *vb, const vop_header *vh) -{ - struct solo_dev *solo_dev = solo_enc->solo_dev; - struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0); - int frame_size; - int ret; - - vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; - - if (vb2_plane_size(vb, 0) < vop_jpeg_size(vh) + solo_enc->jpeg_len) - return -EIO; - - frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN); - vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len); - - /* may discard all previous data in vbuf->sgl */ - dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, - DMA_FROM_DEVICE); - ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf, - vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev), - frame_size, SOLO_JPEG_EXT_ADDR(solo_dev), - SOLO_JPEG_EXT_SIZE(solo_dev)); - dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, - DMA_FROM_DEVICE); - - /* add the header only after dma_unmap_sg() */ - sg_copy_from_buffer(vbuf->sgl, vbuf->nents, - solo_enc->jpeg_header, solo_enc->jpeg_len); - - return ret; -} - -static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, - struct vb2_buffer *vb, const vop_header *vh) -{ - struct solo_dev *solo_dev = solo_enc->solo_dev; - struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0); - int frame_off, frame_size; - int skip = 0; - int ret; - - if (vb2_plane_size(vb, 0) < vop_mpeg_size(vh)) - return -EIO; - - /* If this is a key frame, add extra header */ - vb->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME | - V4L2_BUF_FLAG_BFRAME); - if (!vop_type(vh)) { - skip = solo_enc->vop_len; - vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; - vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh) + - solo_enc->vop_len); - } else { - vb->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; - vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh)); - } - - /* Now get the actual mpeg payload */ - frame_off = (vop_mpeg_offset(vh) - SOLO_MP4E_EXT_ADDR(solo_dev) + - sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev); - frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN); - - /* may discard all previous data in vbuf->sgl */ - dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, - DMA_FROM_DEVICE); - ret = solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size, - SOLO_MP4E_EXT_ADDR(solo_dev), - SOLO_MP4E_EXT_SIZE(solo_dev)); - dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents, - DMA_FROM_DEVICE); - - /* add the header only after dma_unmap_sg() */ - if (!vop_type(vh)) - sg_copy_from_buffer(vbuf->sgl, vbuf->nents, - solo_enc->vop, solo_enc->vop_len); - return ret; -} - -static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc, - struct vb2_buffer *vb, struct solo_enc_buf *enc_buf) -{ - const vop_header *vh = enc_buf->vh; - int ret; - - /* Check for motion flags */ - vb->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_MOTION_ON | - V4L2_BUF_FLAG_MOTION_DETECTED); - if (solo_is_motion_on(solo_enc)) { - vb->v4l2_buf.flags |= V4L2_BUF_FLAG_MOTION_ON; - if (enc_buf->motion) - vb->v4l2_buf.flags |= V4L2_BUF_FLAG_MOTION_DETECTED; - } - - switch (solo_enc->fmt) { - case V4L2_PIX_FMT_MPEG4: - case V4L2_PIX_FMT_H264: - ret = solo_fill_mpeg(solo_enc, vb, vh); - break; - default: /* V4L2_PIX_FMT_MJPEG */ - ret = solo_fill_jpeg(solo_enc, vb, vh); - break; - } - - if (!ret) { - vb->v4l2_buf.sequence = solo_enc->sequence++; - vb->v4l2_buf.timestamp.tv_sec = vop_sec(vh); - vb->v4l2_buf.timestamp.tv_usec = vop_usec(vh); - } - - vb2_buffer_done(vb, ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); - - return ret; -} - -static void solo_enc_handle_one(struct solo_enc_dev *solo_enc, - struct solo_enc_buf *enc_buf) -{ - struct solo_vb2_buf *vb; - unsigned long flags; - - mutex_lock(&solo_enc->lock); - if (solo_enc->type != enc_buf->type) - goto unlock; - - spin_lock_irqsave(&solo_enc->av_lock, flags); - if (list_empty(&solo_enc->vidq_active)) { - spin_unlock_irqrestore(&solo_enc->av_lock, flags); - goto unlock; - } - vb = list_first_entry(&solo_enc->vidq_active, struct solo_vb2_buf, - list); - list_del(&vb->list); - spin_unlock_irqrestore(&solo_enc->av_lock, flags); - - solo_enc_fillbuf(solo_enc, &vb->vb, enc_buf); -unlock: - mutex_unlock(&solo_enc->lock); -} - -void solo_enc_v4l2_isr(struct solo_dev *solo_dev) -{ - wake_up_interruptible_all(&solo_dev->ring_thread_wait); -} - -static void solo_handle_ring(struct solo_dev *solo_dev) -{ - for (;;) { - struct solo_enc_dev *solo_enc; - struct solo_enc_buf enc_buf; - u32 mpeg_current, off; - u8 ch; - u8 cur_q; - - /* Check if the hardware has any new ones in the queue */ - cur_q = solo_reg_read(solo_dev, SOLO_VE_STATE(11)) & 0xff; - if (cur_q == solo_dev->enc_idx) - break; - - mpeg_current = solo_reg_read(solo_dev, - SOLO_VE_MPEG4_QUE(solo_dev->enc_idx)); - solo_dev->enc_idx = (solo_dev->enc_idx + 1) % MP4_QS; - - ch = (mpeg_current >> 24) & 0x1f; - off = mpeg_current & 0x00ffffff; - - if (ch >= SOLO_MAX_CHANNELS) { - ch -= SOLO_MAX_CHANNELS; - enc_buf.type = SOLO_ENC_TYPE_EXT; - } else - enc_buf.type = SOLO_ENC_TYPE_STD; - - solo_enc = solo_dev->v4l2_enc[ch]; - if (solo_enc == NULL) { - dev_err(&solo_dev->pdev->dev, - "Got spurious packet for channel %d\n", ch); - continue; - } - - /* FAIL... */ - if (enc_get_mpeg_dma(solo_dev, solo_dev->vh_dma, off, - sizeof(vop_header))) - continue; - - enc_buf.vh = solo_dev->vh_buf; - - /* Sanity check */ - if (vop_mpeg_offset(enc_buf.vh) != - SOLO_MP4E_EXT_ADDR(solo_dev) + off) - continue; - - if (solo_motion_detected(solo_enc)) - enc_buf.motion = 1; - else - enc_buf.motion = 0; - - solo_enc_handle_one(solo_enc, &enc_buf); - } -} - -static int solo_ring_thread(void *data) -{ - struct solo_dev *solo_dev = data; - DECLARE_WAITQUEUE(wait, current); - - set_freezable(); - add_wait_queue(&solo_dev->ring_thread_wait, &wait); - - for (;;) { - long timeout = schedule_timeout_interruptible(HZ); - if (timeout == -ERESTARTSYS || kthread_should_stop()) - break; - solo_irq_off(solo_dev, SOLO_IRQ_ENCODER); - solo_handle_ring(solo_dev); - solo_irq_on(solo_dev, SOLO_IRQ_ENCODER); - try_to_freeze(); - } - - remove_wait_queue(&solo_dev->ring_thread_wait, &wait); - - return 0; -} - -static int solo_enc_queue_setup(struct vb2_queue *q, - const struct v4l2_format *fmt, - unsigned int *num_buffers, - unsigned int *num_planes, unsigned int sizes[], - void *alloc_ctxs[]) -{ - sizes[0] = FRAME_BUF_SIZE; - *num_planes = 1; - - if (*num_buffers < MIN_VID_BUFFERS) - *num_buffers = MIN_VID_BUFFERS; - - return 0; -} - -static void solo_enc_buf_queue(struct vb2_buffer *vb) -{ - struct vb2_queue *vq = vb->vb2_queue; - struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vq); - struct solo_vb2_buf *solo_vb = - container_of(vb, struct solo_vb2_buf, vb); - - spin_lock(&solo_enc->av_lock); - list_add_tail(&solo_vb->list, &solo_enc->vidq_active); - spin_unlock(&solo_enc->av_lock); -} - -static int solo_ring_start(struct solo_dev *solo_dev) -{ - solo_dev->ring_thread = kthread_run(solo_ring_thread, solo_dev, - SOLO6X10_NAME "_ring"); - if (IS_ERR(solo_dev->ring_thread)) { - int err = PTR_ERR(solo_dev->ring_thread); - solo_dev->ring_thread = NULL; - return err; - } - - solo_irq_on(solo_dev, SOLO_IRQ_ENCODER); - - return 0; -} - -static void solo_ring_stop(struct solo_dev *solo_dev) -{ - if (solo_dev->ring_thread) { - kthread_stop(solo_dev->ring_thread); - solo_dev->ring_thread = NULL; - } - - solo_irq_off(solo_dev, SOLO_IRQ_ENCODER); -} - -static int solo_enc_start_streaming(struct vb2_queue *q, unsigned int count) -{ - struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q); - int ret; - - ret = solo_enc_on(solo_enc); - if (ret) - return ret; - return solo_ring_start(solo_enc->solo_dev); -} - -static void solo_enc_stop_streaming(struct vb2_queue *q) -{ - struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q); - - solo_enc_off(solo_enc); - INIT_LIST_HEAD(&solo_enc->vidq_active); - solo_ring_stop(solo_enc->solo_dev); -} - -static struct vb2_ops solo_enc_video_qops = { - .queue_setup = solo_enc_queue_setup, - .buf_queue = solo_enc_buf_queue, - .start_streaming = solo_enc_start_streaming, - .stop_streaming = solo_enc_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -static int solo_enc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct solo_enc_dev *solo_enc = video_drvdata(file); - struct solo_dev *solo_dev = solo_enc->solo_dev; - - strcpy(cap->driver, SOLO6X10_NAME); - snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d", - solo_enc->ch); - snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", - pci_name(solo_dev->pdev)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int solo_enc_enum_input(struct file *file, void *priv, - struct v4l2_input *input) -{ - struct solo_enc_dev *solo_enc = video_drvdata(file); - struct solo_dev *solo_dev = solo_enc->solo_dev; - - if (input->index) - return -EINVAL; - - snprintf(input->name, sizeof(input->name), "Encoder %d", - solo_enc->ch + 1); - input->type = V4L2_INPUT_TYPE_CAMERA; - input->std = solo_enc->vfd->tvnorms; - - if (!tw28_get_video_status(solo_dev, solo_enc->ch)) - input->status = V4L2_IN_ST_NO_SIGNAL; - - return 0; -} - -static int solo_enc_set_input(struct file *file, void *priv, - unsigned int index) -{ - if (index) - return -EINVAL; - - return 0; -} - -static int solo_enc_get_input(struct file *file, void *priv, - unsigned int *index) -{ - *index = 0; - - return 0; -} - -static int solo_enc_enum_fmt_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct solo_enc_dev *solo_enc = video_drvdata(file); - int dev_type = solo_enc->solo_dev->type; - - switch (f->index) { - case 0: - switch (dev_type) { - case SOLO_DEV_6010: - f->pixelformat = V4L2_PIX_FMT_MPEG4; - strcpy(f->description, "MPEG-4 part 2"); - break; - case SOLO_DEV_6110: - f->pixelformat = V4L2_PIX_FMT_H264; - strcpy(f->description, "H.264"); - break; - } - break; - case 1: - f->pixelformat = V4L2_PIX_FMT_MJPEG; - strcpy(f->description, "MJPEG"); - break; - default: - return -EINVAL; - } - - f->flags = V4L2_FMT_FLAG_COMPRESSED; - - return 0; -} - -static inline int solo_valid_pixfmt(u32 pixfmt, int dev_type) -{ - return (pixfmt == V4L2_PIX_FMT_H264 && dev_type == SOLO_DEV_6110) - || (pixfmt == V4L2_PIX_FMT_MPEG4 && dev_type == SOLO_DEV_6010) - || pixfmt == V4L2_PIX_FMT_MJPEG ? 0 : -EINVAL; -} - -static int solo_enc_try_fmt_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct solo_enc_dev *solo_enc = video_drvdata(file); - struct solo_dev *solo_dev = solo_enc->solo_dev; - struct v4l2_pix_format *pix = &f->fmt.pix; - - if (solo_valid_pixfmt(pix->pixelformat, solo_dev->type)) - return -EINVAL; - - if (pix->width < solo_dev->video_hsize || - pix->height < solo_dev->video_vsize << 1) { - /* Default to CIF 1/2 size */ - pix->width = solo_dev->video_hsize >> 1; - pix->height = solo_dev->video_vsize; - } else { - /* Full frame */ - pix->width = solo_dev->video_hsize; - pix->height = solo_dev->video_vsize << 1; - } - - switch (pix->field) { - case V4L2_FIELD_NONE: - case V4L2_FIELD_INTERLACED: - break; - case V4L2_FIELD_ANY: - default: - pix->field = V4L2_FIELD_INTERLACED; - break; - } - - /* Just set these */ - pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - pix->sizeimage = FRAME_BUF_SIZE; - pix->bytesperline = 0; - pix->priv = 0; - - return 0; -} - -static int solo_enc_set_fmt_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct solo_enc_dev *solo_enc = video_drvdata(file); - struct solo_dev *solo_dev = solo_enc->solo_dev; - struct v4l2_pix_format *pix = &f->fmt.pix; - int ret; - - if (vb2_is_busy(&solo_enc->vidq)) - return -EBUSY; - - ret = solo_enc_try_fmt_cap(file, priv, f); - if (ret) - return ret; - - if (pix->width == solo_dev->video_hsize) - solo_enc->mode = SOLO_ENC_MODE_D1; - else - solo_enc->mode = SOLO_ENC_MODE_CIF; - - /* This does not change the encoder at all */ - solo_enc->fmt = pix->pixelformat; - - /* - * More information is needed about these 'extended' types. As far - * as I can tell these are basically additional video streams with - * different MPEG encoding attributes that can run in parallel with - * the main stream. If so, then this should be implemented as a - * second video node. Abusing priv like this is certainly not the - * right approach. - if (pix->priv) - solo_enc->type = SOLO_ENC_TYPE_EXT; - */ - solo_update_mode(solo_enc); - return 0; -} - -static int solo_enc_get_fmt_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct solo_enc_dev *solo_enc = video_drvdata(file); - struct v4l2_pix_format *pix = &f->fmt.pix; - - pix->width = solo_enc->width; - pix->height = solo_enc->height; - pix->pixelformat = solo_enc->fmt; - pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED : - V4L2_FIELD_NONE; - pix->sizeimage = FRAME_BUF_SIZE; - pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - pix->priv = 0; - - return 0; -} - -static int solo_enc_g_std(struct file *file, void *priv, v4l2_std_id *i) -{ - struct solo_enc_dev *solo_enc = video_drvdata(file); - struct solo_dev *solo_dev = solo_enc->solo_dev; - - if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) - *i = V4L2_STD_NTSC_M; - else - *i = V4L2_STD_PAL; - return 0; -} - -static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id std) -{ - struct solo_enc_dev *solo_enc = video_drvdata(file); - - return solo_set_video_type(solo_enc->solo_dev, std & V4L2_STD_625_50); -} - -static int solo_enum_framesizes(struct file *file, void *priv, - struct v4l2_frmsizeenum *fsize) -{ - struct solo_enc_dev *solo_enc = video_drvdata(file); - struct solo_dev *solo_dev = solo_enc->solo_dev; - - if (solo_valid_pixfmt(fsize->pixel_format, solo_dev->type)) - return -EINVAL; - - switch (fsize->index) { - case 0: - fsize->discrete.width = solo_dev->video_hsize >> 1; - fsize->discrete.height = solo_dev->video_vsize; - break; - case 1: - fsize->discrete.width = solo_dev->video_hsize; - fsize->discrete.height = solo_dev->video_vsize << 1; - break; - default: - return -EINVAL; - } - - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - - return 0; -} - -static int solo_enum_frameintervals(struct file *file, void *priv, - struct v4l2_frmivalenum *fintv) -{ - struct solo_enc_dev *solo_enc = video_drvdata(file); - struct solo_dev *solo_dev = solo_enc->solo_dev; - - if (solo_valid_pixfmt(fintv->pixel_format, solo_dev->type)) - return -EINVAL; - if (fintv->index) - return -EINVAL; - if ((fintv->width != solo_dev->video_hsize >> 1 || - fintv->height != solo_dev->video_vsize) && - (fintv->width != solo_dev->video_hsize || - fintv->height != solo_dev->video_vsize << 1)) - return -EINVAL; - - fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE; - - fintv->stepwise.min.numerator = 1; - fintv->stepwise.min.denominator = solo_dev->fps; - - fintv->stepwise.max.numerator = 15; - fintv->stepwise.max.denominator = solo_dev->fps; - - fintv->stepwise.step.numerator = 1; - fintv->stepwise.step.denominator = solo_dev->fps; - - return 0; -} - -static int solo_g_parm(struct file *file, void *priv, - struct v4l2_streamparm *sp) -{ - struct solo_enc_dev *solo_enc = video_drvdata(file); - struct v4l2_captureparm *cp = &sp->parm.capture; - - cp->capability = V4L2_CAP_TIMEPERFRAME; - cp->timeperframe.numerator = solo_enc->interval; - cp->timeperframe.denominator = solo_enc->solo_dev->fps; - cp->capturemode = 0; - /* XXX: Shouldn't we be able to get/set this from videobuf? */ - cp->readbuffers = 2; - - return 0; -} - -static inline int calc_interval(u8 fps, u32 n, u32 d) -{ - if (!n || !d) - return 1; - if (d == fps) - return n; - n *= fps; - return min(15U, n / d + (n % d >= (fps >> 1))); -} - -static int solo_s_parm(struct file *file, void *priv, - struct v4l2_streamparm *sp) -{ - struct solo_enc_dev *solo_enc = video_drvdata(file); - struct v4l2_fract *t = &sp->parm.capture.timeperframe; - u8 fps = solo_enc->solo_dev->fps; - - if (vb2_is_streaming(&solo_enc->vidq)) - return -EBUSY; - - solo_enc->interval = calc_interval(fps, t->numerator, t->denominator); - solo_update_mode(solo_enc); - return solo_g_parm(file, priv, sp); -} - -static long solo_enc_default(struct file *file, void *fh, - bool valid_prio, unsigned int cmd, void *arg) -{ - struct solo_enc_dev *solo_enc = video_drvdata(file); - struct solo_dev *solo_dev = solo_enc->solo_dev; - struct solo_motion_thresholds *thresholds = arg; - - switch (cmd) { - case SOLO_IOC_G_MOTION_THRESHOLDS: - *thresholds = solo_enc->motion_thresholds; - return 0; - - case SOLO_IOC_S_MOTION_THRESHOLDS: - if (!valid_prio) - return -EBUSY; - solo_enc->motion_thresholds = *thresholds; - if (solo_enc->motion_enabled && !solo_enc->motion_global) - return solo_set_motion_block(solo_dev, solo_enc->ch, - &solo_enc->motion_thresholds); - return 0; - default: - return -ENOTTY; - } -} - -static int solo_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct solo_enc_dev *solo_enc = - container_of(ctrl->handler, struct solo_enc_dev, hdl); - struct solo_dev *solo_dev = solo_enc->solo_dev; - int err; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - case V4L2_CID_CONTRAST: - case V4L2_CID_SATURATION: - case V4L2_CID_HUE: - case V4L2_CID_SHARPNESS: - return tw28_set_ctrl_val(solo_dev, ctrl->id, solo_enc->ch, - ctrl->val); - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - solo_enc->gop = ctrl->val; - return 0; - case V4L2_CID_MOTION_THRESHOLD: - solo_enc->motion_thresh = ctrl->val; - if (!solo_enc->motion_global || !solo_enc->motion_enabled) - return 0; - return solo_set_motion_threshold(solo_dev, solo_enc->ch, - ctrl->val); - case V4L2_CID_MOTION_MODE: - solo_enc->motion_global = ctrl->val == 1; - solo_enc->motion_enabled = ctrl->val > 0; - if (ctrl->val) { - if (solo_enc->motion_global) - solo_set_motion_threshold(solo_dev, - solo_enc->ch, solo_enc->motion_thresh); - else - solo_set_motion_block(solo_dev, solo_enc->ch, - &solo_enc->motion_thresholds); - } - solo_motion_toggle(solo_enc, ctrl->val); - return 0; - case V4L2_CID_OSD_TEXT: - strcpy(solo_enc->osd_text, ctrl->string); - err = solo_osd_print(solo_enc); - return err; - default: - return -EINVAL; - } - - return 0; -} - -static const struct v4l2_file_operations solo_enc_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = vb2_fop_release, - .read = vb2_fop_read, - .poll = vb2_fop_poll, - .mmap = vb2_fop_mmap, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = { - .vidioc_querycap = solo_enc_querycap, - .vidioc_s_std = solo_enc_s_std, - .vidioc_g_std = solo_enc_g_std, - /* Input callbacks */ - .vidioc_enum_input = solo_enc_enum_input, - .vidioc_s_input = solo_enc_set_input, - .vidioc_g_input = solo_enc_get_input, - /* Video capture format callbacks */ - .vidioc_enum_fmt_vid_cap = solo_enc_enum_fmt_cap, - .vidioc_try_fmt_vid_cap = solo_enc_try_fmt_cap, - .vidioc_s_fmt_vid_cap = solo_enc_set_fmt_cap, - .vidioc_g_fmt_vid_cap = solo_enc_get_fmt_cap, - /* Streaming I/O */ - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - /* Frame size and interval */ - .vidioc_enum_framesizes = solo_enum_framesizes, - .vidioc_enum_frameintervals = solo_enum_frameintervals, - /* Video capture parameters */ - .vidioc_s_parm = solo_s_parm, - .vidioc_g_parm = solo_g_parm, - /* Logging and events */ - .vidioc_log_status = v4l2_ctrl_log_status, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_default = solo_enc_default, -}; - -static const struct video_device solo_enc_template = { - .name = SOLO6X10_NAME, - .fops = &solo_enc_fops, - .ioctl_ops = &solo_enc_ioctl_ops, - .minor = -1, - .release = video_device_release, - .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL, -}; - -static const struct v4l2_ctrl_ops solo_ctrl_ops = { - .s_ctrl = solo_s_ctrl, -}; - -static const struct v4l2_ctrl_config solo_motion_threshold_ctrl = { - .ops = &solo_ctrl_ops, - .id = V4L2_CID_MOTION_THRESHOLD, - .name = "Motion Detection Threshold", - .type = V4L2_CTRL_TYPE_INTEGER, - .max = 0xffff, - .def = SOLO_DEF_MOT_THRESH, - .step = 1, - .flags = V4L2_CTRL_FLAG_SLIDER, -}; - -static const char * const solo_motion_mode_menu[] = { - "Disabled", - "Global Threshold", - "Regional Threshold", - NULL -}; - -static const struct v4l2_ctrl_config solo_motion_enable_ctrl = { - .ops = &solo_ctrl_ops, - .id = V4L2_CID_MOTION_MODE, - .name = "Motion Detection Mode", - .type = V4L2_CTRL_TYPE_MENU, - .qmenu = solo_motion_mode_menu, - .max = 2, -}; - -static const struct v4l2_ctrl_config solo_osd_text_ctrl = { - .ops = &solo_ctrl_ops, - .id = V4L2_CID_OSD_TEXT, - .name = "OSD Text", - .type = V4L2_CTRL_TYPE_STRING, - .max = OSD_TEXT_MAX, - .step = 1, -}; - -static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, - u8 ch, unsigned nr) -{ - struct solo_enc_dev *solo_enc; - struct v4l2_ctrl_handler *hdl; - int ret; - int x, y; - - solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL); - if (!solo_enc) - return ERR_PTR(-ENOMEM); - - hdl = &solo_enc->hdl; - v4l2_ctrl_handler_init(hdl, 10); - v4l2_ctrl_new_std(hdl, &solo_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); - v4l2_ctrl_new_std(hdl, &solo_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, 128); - v4l2_ctrl_new_std(hdl, &solo_ctrl_ops, - V4L2_CID_SATURATION, 0, 255, 1, 128); - v4l2_ctrl_new_std(hdl, &solo_ctrl_ops, - V4L2_CID_HUE, 0, 255, 1, 128); - if (tw28_has_sharpness(solo_dev, ch)) - v4l2_ctrl_new_std(hdl, &solo_ctrl_ops, - V4L2_CID_SHARPNESS, 0, 15, 1, 0); - v4l2_ctrl_new_std(hdl, &solo_ctrl_ops, - V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, solo_dev->fps); - v4l2_ctrl_new_custom(hdl, &solo_motion_threshold_ctrl, NULL); - v4l2_ctrl_new_custom(hdl, &solo_motion_enable_ctrl, NULL); - v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL); - if (hdl->error) { - ret = hdl->error; - goto hdl_free; - } - - solo_enc->solo_dev = solo_dev; - solo_enc->ch = ch; - mutex_init(&solo_enc->lock); - spin_lock_init(&solo_enc->av_lock); - INIT_LIST_HEAD(&solo_enc->vidq_active); - solo_enc->fmt = (solo_dev->type == SOLO_DEV_6010) ? - V4L2_PIX_FMT_MPEG4 : V4L2_PIX_FMT_H264; - solo_enc->type = SOLO_ENC_TYPE_STD; - - solo_enc->qp = SOLO_DEFAULT_QP; - solo_enc->gop = solo_dev->fps; - solo_enc->interval = 1; - solo_enc->mode = SOLO_ENC_MODE_CIF; - solo_enc->motion_global = true; - solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH; - for (y = 0; y < SOLO_MOTION_SZ; y++) - for (x = 0; x < SOLO_MOTION_SZ; x++) - solo_enc->motion_thresholds.thresholds[y][x] = - SOLO_DEF_MOT_THRESH; - - solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; - solo_enc->vidq.ops = &solo_enc_video_qops; - solo_enc->vidq.mem_ops = &vb2_dma_sg_memops; - solo_enc->vidq.drv_priv = solo_enc; - solo_enc->vidq.gfp_flags = __GFP_DMA32; - solo_enc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf); - solo_enc->vidq.lock = &solo_enc->lock; - ret = vb2_queue_init(&solo_enc->vidq); - if (ret) - goto hdl_free; - solo_update_mode(solo_enc); - - spin_lock_init(&solo_enc->motion_lock); - - /* Initialize this per encoder */ - solo_enc->jpeg_len = sizeof(jpeg_header); - memcpy(solo_enc->jpeg_header, jpeg_header, solo_enc->jpeg_len); - - solo_enc->desc_nelts = 32; - solo_enc->desc_items = pci_alloc_consistent(solo_dev->pdev, - sizeof(struct solo_p2m_desc) * - solo_enc->desc_nelts, - &solo_enc->desc_dma); - ret = -ENOMEM; - if (solo_enc->desc_items == NULL) - goto hdl_free; - - solo_enc->vfd = video_device_alloc(); - if (!solo_enc->vfd) - goto pci_free; - - *solo_enc->vfd = solo_enc_template; - solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev; - solo_enc->vfd->ctrl_handler = hdl; - solo_enc->vfd->queue = &solo_enc->vidq; - solo_enc->vfd->lock = &solo_enc->lock; - set_bit(V4L2_FL_USE_FH_PRIO, &solo_enc->vfd->flags); - video_set_drvdata(solo_enc->vfd, solo_enc); - ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr); - if (ret < 0) - goto vdev_release; - - snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name), - "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num, - solo_enc->vfd->num); - - return solo_enc; - -vdev_release: - video_device_release(solo_enc->vfd); -pci_free: - pci_free_consistent(solo_enc->solo_dev->pdev, - sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts, - solo_enc->desc_items, solo_enc->desc_dma); -hdl_free: - v4l2_ctrl_handler_free(hdl); - kfree(solo_enc); - return ERR_PTR(ret); -} - -static void solo_enc_free(struct solo_enc_dev *solo_enc) -{ - if (solo_enc == NULL) - return; - - video_unregister_device(solo_enc->vfd); - v4l2_ctrl_handler_free(&solo_enc->hdl); - kfree(solo_enc); -} - -int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr) -{ - int i; - - init_waitqueue_head(&solo_dev->ring_thread_wait); - - solo_dev->vh_size = sizeof(vop_header); - solo_dev->vh_buf = pci_alloc_consistent(solo_dev->pdev, - solo_dev->vh_size, - &solo_dev->vh_dma); - if (solo_dev->vh_buf == NULL) - return -ENOMEM; - - for (i = 0; i < solo_dev->nr_chans; i++) { - solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i, nr); - if (IS_ERR(solo_dev->v4l2_enc[i])) - break; - } - - if (i != solo_dev->nr_chans) { - int ret = PTR_ERR(solo_dev->v4l2_enc[i]); - while (i--) - solo_enc_free(solo_dev->v4l2_enc[i]); - pci_free_consistent(solo_dev->pdev, solo_dev->vh_size, - solo_dev->vh_buf, solo_dev->vh_dma); - solo_dev->vh_buf = NULL; - return ret; - } - - if (solo_dev->type == SOLO_DEV_6010) - solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4; - else - solo_dev->enc_bw_remain = solo_dev->fps * 4 * 5; - - dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n", - solo_dev->v4l2_enc[0]->vfd->num, - solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num); - - return 0; -} - -void solo_enc_v4l2_exit(struct solo_dev *solo_dev) -{ - int i; - - for (i = 0; i < solo_dev->nr_chans; i++) - solo_enc_free(solo_dev->v4l2_enc[i]); - - if (solo_dev->vh_buf) - pci_free_consistent(solo_dev->pdev, solo_dev->vh_size, - solo_dev->vh_buf, solo_dev->vh_dma); -} diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2.c b/drivers/staging/media/solo6x10/solo6x10-v4l2.c deleted file mode 100644 index 5d0100eb38e6..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10-v4l2.c +++ /dev/null @@ -1,734 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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/kernel.h> -#include <linux/module.h> -#include <linux/kthread.h> -#include <linux/freezer.h> - -#include <media/v4l2-ioctl.h> -#include <media/v4l2-common.h> -#include <media/v4l2-event.h> -#include <media/videobuf2-dma-contig.h> - -#include "solo6x10.h" -#include "solo6x10-tw28.h" - -/* Image size is two fields, SOLO_HW_BPL is one horizontal line in hardware */ -#define SOLO_HW_BPL 2048 -#define solo_vlines(__solo) (__solo->video_vsize * 2) -#define solo_image_size(__solo) (solo_bytesperline(__solo) * \ - solo_vlines(__solo)) -#define solo_bytesperline(__solo) (__solo->video_hsize * 2) - -#define MIN_VID_BUFFERS 2 - -static inline void erase_on(struct solo_dev *solo_dev) -{ - solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON); - solo_dev->erasing = 1; - solo_dev->frame_blank = 0; -} - -static inline int erase_off(struct solo_dev *solo_dev) -{ - if (!solo_dev->erasing) - return 0; - - /* First time around, assert erase off */ - if (!solo_dev->frame_blank) - solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, 0); - /* Keep the erasing flag on for 8 frames minimum */ - if (solo_dev->frame_blank++ >= 8) - solo_dev->erasing = 0; - - return 1; -} - -void solo_video_in_isr(struct solo_dev *solo_dev) -{ - wake_up_interruptible_all(&solo_dev->disp_thread_wait); -} - -static void solo_win_setup(struct solo_dev *solo_dev, u8 ch, - int sx, int sy, int ex, int ey, int scale) -{ - if (ch >= solo_dev->nr_chans) - return; - - /* Here, we just keep window/channel the same */ - solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(ch), - SOLO_VI_WIN_CHANNEL(ch) | - SOLO_VI_WIN_SX(sx) | - SOLO_VI_WIN_EX(ex) | - SOLO_VI_WIN_SCALE(scale)); - - solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(ch), - SOLO_VI_WIN_SY(sy) | - SOLO_VI_WIN_EY(ey)); -} - -static int solo_v4l2_ch_ext_4up(struct solo_dev *solo_dev, u8 idx, int on) -{ - u8 ch = idx * 4; - - if (ch >= solo_dev->nr_chans) - return -EINVAL; - - if (!on) { - u8 i; - for (i = ch; i < ch + 4; i++) - solo_win_setup(solo_dev, i, solo_dev->video_hsize, - solo_vlines(solo_dev), - solo_dev->video_hsize, - solo_vlines(solo_dev), 0); - return 0; - } - - /* Row 1 */ - solo_win_setup(solo_dev, ch, 0, 0, solo_dev->video_hsize / 2, - solo_vlines(solo_dev) / 2, 3); - solo_win_setup(solo_dev, ch + 1, solo_dev->video_hsize / 2, 0, - solo_dev->video_hsize, solo_vlines(solo_dev) / 2, 3); - /* Row 2 */ - solo_win_setup(solo_dev, ch + 2, 0, solo_vlines(solo_dev) / 2, - solo_dev->video_hsize / 2, solo_vlines(solo_dev), 3); - solo_win_setup(solo_dev, ch + 3, solo_dev->video_hsize / 2, - solo_vlines(solo_dev) / 2, solo_dev->video_hsize, - solo_vlines(solo_dev), 3); - - return 0; -} - -static int solo_v4l2_ch_ext_16up(struct solo_dev *solo_dev, int on) -{ - int sy, ysize, hsize, i; - - if (!on) { - for (i = 0; i < 16; i++) - solo_win_setup(solo_dev, i, solo_dev->video_hsize, - solo_vlines(solo_dev), - solo_dev->video_hsize, - solo_vlines(solo_dev), 0); - return 0; - } - - ysize = solo_vlines(solo_dev) / 4; - hsize = solo_dev->video_hsize / 4; - - for (sy = 0, i = 0; i < 4; i++, sy += ysize) { - solo_win_setup(solo_dev, i * 4, 0, sy, hsize, - sy + ysize, 5); - solo_win_setup(solo_dev, (i * 4) + 1, hsize, sy, - hsize * 2, sy + ysize, 5); - solo_win_setup(solo_dev, (i * 4) + 2, hsize * 2, sy, - hsize * 3, sy + ysize, 5); - solo_win_setup(solo_dev, (i * 4) + 3, hsize * 3, sy, - solo_dev->video_hsize, sy + ysize, 5); - } - - return 0; -} - -static int solo_v4l2_ch(struct solo_dev *solo_dev, u8 ch, int on) -{ - u8 ext_ch; - - if (ch < solo_dev->nr_chans) { - solo_win_setup(solo_dev, ch, on ? 0 : solo_dev->video_hsize, - on ? 0 : solo_vlines(solo_dev), - solo_dev->video_hsize, solo_vlines(solo_dev), - on ? 1 : 0); - return 0; - } - - if (ch >= solo_dev->nr_chans + solo_dev->nr_ext) - return -EINVAL; - - ext_ch = ch - solo_dev->nr_chans; - - /* 4up's first */ - if (ext_ch < 4) - return solo_v4l2_ch_ext_4up(solo_dev, ext_ch, on); - - /* Remaining case is 16up for 16-port */ - return solo_v4l2_ch_ext_16up(solo_dev, on); -} - -static int solo_v4l2_set_ch(struct solo_dev *solo_dev, u8 ch) -{ - if (ch >= solo_dev->nr_chans + solo_dev->nr_ext) - return -EINVAL; - - erase_on(solo_dev); - - solo_v4l2_ch(solo_dev, solo_dev->cur_disp_ch, 0); - solo_v4l2_ch(solo_dev, ch, 1); - - solo_dev->cur_disp_ch = ch; - - return 0; -} - -static void solo_fillbuf(struct solo_dev *solo_dev, - struct vb2_buffer *vb) -{ - dma_addr_t vbuf; - unsigned int fdma_addr; - int error = -1; - int i; - - vbuf = vb2_dma_contig_plane_dma_addr(vb, 0); - if (!vbuf) - goto finish_buf; - - if (erase_off(solo_dev)) { - void *p = vb2_plane_vaddr(vb, 0); - int image_size = solo_image_size(solo_dev); - for (i = 0; i < image_size; i += 2) { - ((u8 *)p)[i] = 0x80; - ((u8 *)p)[i + 1] = 0x00; - } - error = 0; - } else { - fdma_addr = SOLO_DISP_EXT_ADDR + (solo_dev->old_write * - (SOLO_HW_BPL * solo_vlines(solo_dev))); - - error = solo_p2m_dma_t(solo_dev, 0, vbuf, fdma_addr, - solo_bytesperline(solo_dev), - solo_vlines(solo_dev), SOLO_HW_BPL); - } - -finish_buf: - if (!error) { - vb2_set_plane_payload(vb, 0, - solo_vlines(solo_dev) * solo_bytesperline(solo_dev)); - vb->v4l2_buf.sequence = solo_dev->sequence++; - v4l2_get_timestamp(&vb->v4l2_buf.timestamp); - } - - vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); -} - -static void solo_thread_try(struct solo_dev *solo_dev) -{ - struct solo_vb2_buf *vb; - - /* Only "break" from this loop if slock is held, otherwise - * just return. */ - for (;;) { - unsigned int cur_write; - - cur_write = SOLO_VI_STATUS0_PAGE( - solo_reg_read(solo_dev, SOLO_VI_STATUS0)); - if (cur_write == solo_dev->old_write) - return; - - spin_lock(&solo_dev->slock); - - if (list_empty(&solo_dev->vidq_active)) - break; - - vb = list_first_entry(&solo_dev->vidq_active, struct solo_vb2_buf, - list); - - solo_dev->old_write = cur_write; - list_del(&vb->list); - - spin_unlock(&solo_dev->slock); - - solo_fillbuf(solo_dev, &vb->vb); - } - - assert_spin_locked(&solo_dev->slock); - spin_unlock(&solo_dev->slock); -} - -static int solo_thread(void *data) -{ - struct solo_dev *solo_dev = data; - DECLARE_WAITQUEUE(wait, current); - - set_freezable(); - add_wait_queue(&solo_dev->disp_thread_wait, &wait); - - for (;;) { - long timeout = schedule_timeout_interruptible(HZ); - if (timeout == -ERESTARTSYS || kthread_should_stop()) - break; - solo_thread_try(solo_dev); - try_to_freeze(); - } - - remove_wait_queue(&solo_dev->disp_thread_wait, &wait); - - return 0; -} - -static int solo_start_thread(struct solo_dev *solo_dev) -{ - int ret = 0; - - solo_dev->kthread = kthread_run(solo_thread, solo_dev, SOLO6X10_NAME "_disp"); - - if (IS_ERR(solo_dev->kthread)) { - ret = PTR_ERR(solo_dev->kthread); - solo_dev->kthread = NULL; - return ret; - } - solo_irq_on(solo_dev, SOLO_IRQ_VIDEO_IN); - - return ret; -} - -static void solo_stop_thread(struct solo_dev *solo_dev) -{ - if (!solo_dev->kthread) - return; - - solo_irq_off(solo_dev, SOLO_IRQ_VIDEO_IN); - kthread_stop(solo_dev->kthread); - solo_dev->kthread = NULL; -} - -static int solo_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, - unsigned int *num_buffers, unsigned int *num_planes, - unsigned int sizes[], void *alloc_ctxs[]) -{ - struct solo_dev *solo_dev = vb2_get_drv_priv(q); - - sizes[0] = solo_image_size(solo_dev); - alloc_ctxs[0] = solo_dev->alloc_ctx; - *num_planes = 1; - - if (*num_buffers < MIN_VID_BUFFERS) - *num_buffers = MIN_VID_BUFFERS; - - return 0; -} - -static int solo_start_streaming(struct vb2_queue *q, unsigned int count) -{ - struct solo_dev *solo_dev = vb2_get_drv_priv(q); - - solo_dev->sequence = 0; - return solo_start_thread(solo_dev); -} - -static void solo_stop_streaming(struct vb2_queue *q) -{ - struct solo_dev *solo_dev = vb2_get_drv_priv(q); - - solo_stop_thread(solo_dev); - INIT_LIST_HEAD(&solo_dev->vidq_active); -} - -static void solo_buf_queue(struct vb2_buffer *vb) -{ - struct vb2_queue *vq = vb->vb2_queue; - struct solo_dev *solo_dev = vb2_get_drv_priv(vq); - struct solo_vb2_buf *solo_vb = - container_of(vb, struct solo_vb2_buf, vb); - - spin_lock(&solo_dev->slock); - list_add_tail(&solo_vb->list, &solo_dev->vidq_active); - spin_unlock(&solo_dev->slock); - wake_up_interruptible(&solo_dev->disp_thread_wait); -} - -static const struct vb2_ops solo_video_qops = { - .queue_setup = solo_queue_setup, - .buf_queue = solo_buf_queue, - .start_streaming = solo_start_streaming, - .stop_streaming = solo_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -static int solo_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct solo_dev *solo_dev = video_drvdata(file); - - strcpy(cap->driver, SOLO6X10_NAME); - strcpy(cap->card, "Softlogic 6x10"); - snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", - pci_name(solo_dev->pdev)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int solo_enum_ext_input(struct solo_dev *solo_dev, - struct v4l2_input *input) -{ - static const char * const dispnames_1[] = { "4UP" }; - static const char * const dispnames_2[] = { "4UP-1", "4UP-2" }; - static const char * const dispnames_5[] = { - "4UP-1", "4UP-2", "4UP-3", "4UP-4", "16UP" - }; - const char * const *dispnames; - - if (input->index >= (solo_dev->nr_chans + solo_dev->nr_ext)) - return -EINVAL; - - if (solo_dev->nr_ext == 5) - dispnames = dispnames_5; - else if (solo_dev->nr_ext == 2) - dispnames = dispnames_2; - else - dispnames = dispnames_1; - - snprintf(input->name, sizeof(input->name), "Multi %s", - dispnames[input->index - solo_dev->nr_chans]); - - return 0; -} - -static int solo_enum_input(struct file *file, void *priv, - struct v4l2_input *input) -{ - struct solo_dev *solo_dev = video_drvdata(file); - - if (input->index >= solo_dev->nr_chans) { - int ret = solo_enum_ext_input(solo_dev, input); - if (ret < 0) - return ret; - } else { - snprintf(input->name, sizeof(input->name), "Camera %d", - input->index + 1); - - /* We can only check this for normal inputs */ - if (!tw28_get_video_status(solo_dev, input->index)) - input->status = V4L2_IN_ST_NO_SIGNAL; - } - - input->type = V4L2_INPUT_TYPE_CAMERA; - input->std = solo_dev->vfd->tvnorms; - return 0; -} - -static int solo_set_input(struct file *file, void *priv, unsigned int index) -{ - struct solo_dev *solo_dev = video_drvdata(file); - int ret = solo_v4l2_set_ch(solo_dev, index); - - if (!ret) { - while (erase_off(solo_dev)) - /* Do nothing */; - } - - return ret; -} - -static int solo_get_input(struct file *file, void *priv, unsigned int *index) -{ - struct solo_dev *solo_dev = video_drvdata(file); - - *index = solo_dev->cur_disp_ch; - - return 0; -} - -static int solo_enum_fmt_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - if (f->index) - return -EINVAL; - - f->pixelformat = V4L2_PIX_FMT_UYVY; - strlcpy(f->description, "UYUV 4:2:2 Packed", sizeof(f->description)); - - return 0; -} - -static int solo_try_fmt_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct solo_dev *solo_dev = video_drvdata(file); - struct v4l2_pix_format *pix = &f->fmt.pix; - int image_size = solo_image_size(solo_dev); - - if (pix->pixelformat != V4L2_PIX_FMT_UYVY) - return -EINVAL; - - pix->width = solo_dev->video_hsize; - pix->height = solo_vlines(solo_dev); - pix->sizeimage = image_size; - pix->field = V4L2_FIELD_INTERLACED; - pix->pixelformat = V4L2_PIX_FMT_UYVY; - pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - pix->priv = 0; - return 0; -} - -static int solo_set_fmt_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct solo_dev *solo_dev = video_drvdata(file); - - if (vb2_is_busy(&solo_dev->vidq)) - return -EBUSY; - - /* For right now, if it doesn't match our running config, - * then fail */ - return solo_try_fmt_cap(file, priv, f); -} - -static int solo_get_fmt_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct solo_dev *solo_dev = video_drvdata(file); - struct v4l2_pix_format *pix = &f->fmt.pix; - - pix->width = solo_dev->video_hsize; - pix->height = solo_vlines(solo_dev); - pix->pixelformat = V4L2_PIX_FMT_UYVY; - pix->field = V4L2_FIELD_INTERLACED; - pix->sizeimage = solo_image_size(solo_dev); - pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - pix->bytesperline = solo_bytesperline(solo_dev); - pix->priv = 0; - - return 0; -} - -static int solo_g_std(struct file *file, void *priv, v4l2_std_id *i) -{ - struct solo_dev *solo_dev = video_drvdata(file); - - if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) - *i = V4L2_STD_NTSC_M; - else - *i = V4L2_STD_PAL; - return 0; -} - -int solo_set_video_type(struct solo_dev *solo_dev, bool is_50hz) -{ - int i; - - /* Make sure all video nodes are idle */ - if (vb2_is_busy(&solo_dev->vidq)) - return -EBUSY; - for (i = 0; i < solo_dev->nr_chans; i++) - if (vb2_is_busy(&solo_dev->v4l2_enc[i]->vidq)) - return -EBUSY; - solo_dev->video_type = is_50hz ? SOLO_VO_FMT_TYPE_PAL : - SOLO_VO_FMT_TYPE_NTSC; - /* Reconfigure for the new standard */ - solo_disp_init(solo_dev); - solo_enc_init(solo_dev); - solo_tw28_init(solo_dev); - for (i = 0; i < solo_dev->nr_chans; i++) - solo_update_mode(solo_dev->v4l2_enc[i]); - return solo_v4l2_set_ch(solo_dev, solo_dev->cur_disp_ch); -} - -static int solo_s_std(struct file *file, void *priv, v4l2_std_id std) -{ - struct solo_dev *solo_dev = video_drvdata(file); - - return solo_set_video_type(solo_dev, std & V4L2_STD_625_50); -} - -static int solo_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct solo_dev *solo_dev = - container_of(ctrl->handler, struct solo_dev, disp_hdl); - - switch (ctrl->id) { - case V4L2_CID_MOTION_TRACE: - if (ctrl->val) { - solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, - SOLO_VI_MOTION_Y_ADD | - SOLO_VI_MOTION_Y_VALUE(0x20) | - SOLO_VI_MOTION_CB_VALUE(0x10) | - SOLO_VI_MOTION_CR_VALUE(0x10)); - solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, - SOLO_VI_MOTION_CR_ADD | - SOLO_VI_MOTION_Y_VALUE(0x10) | - SOLO_VI_MOTION_CB_VALUE(0x80) | - SOLO_VI_MOTION_CR_VALUE(0x10)); - } else { - solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0); - solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0); - } - return 0; - default: - break; - } - return -EINVAL; -} - -static const struct v4l2_file_operations solo_v4l2_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = vb2_fop_release, - .read = vb2_fop_read, - .poll = vb2_fop_poll, - .mmap = vb2_fop_mmap, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops = { - .vidioc_querycap = solo_querycap, - .vidioc_s_std = solo_s_std, - .vidioc_g_std = solo_g_std, - /* Input callbacks */ - .vidioc_enum_input = solo_enum_input, - .vidioc_s_input = solo_set_input, - .vidioc_g_input = solo_get_input, - /* Video capture format callbacks */ - .vidioc_enum_fmt_vid_cap = solo_enum_fmt_cap, - .vidioc_try_fmt_vid_cap = solo_try_fmt_cap, - .vidioc_s_fmt_vid_cap = solo_set_fmt_cap, - .vidioc_g_fmt_vid_cap = solo_get_fmt_cap, - /* Streaming I/O */ - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - /* Logging and events */ - .vidioc_log_status = v4l2_ctrl_log_status, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static struct video_device solo_v4l2_template = { - .name = SOLO6X10_NAME, - .fops = &solo_v4l2_fops, - .ioctl_ops = &solo_v4l2_ioctl_ops, - .minor = -1, - .release = video_device_release, - .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL, -}; - -static const struct v4l2_ctrl_ops solo_ctrl_ops = { - .s_ctrl = solo_s_ctrl, -}; - -static const struct v4l2_ctrl_config solo_motion_trace_ctrl = { - .ops = &solo_ctrl_ops, - .id = V4L2_CID_MOTION_TRACE, - .name = "Motion Detection Trace", - .type = V4L2_CTRL_TYPE_BOOLEAN, - .max = 1, - .step = 1, -}; - -int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr) -{ - int ret; - int i; - - init_waitqueue_head(&solo_dev->disp_thread_wait); - spin_lock_init(&solo_dev->slock); - mutex_init(&solo_dev->lock); - INIT_LIST_HEAD(&solo_dev->vidq_active); - - solo_dev->vfd = video_device_alloc(); - if (!solo_dev->vfd) - return -ENOMEM; - - *solo_dev->vfd = solo_v4l2_template; - solo_dev->vfd->v4l2_dev = &solo_dev->v4l2_dev; - solo_dev->vfd->queue = &solo_dev->vidq; - solo_dev->vfd->lock = &solo_dev->lock; - v4l2_ctrl_handler_init(&solo_dev->disp_hdl, 1); - v4l2_ctrl_new_custom(&solo_dev->disp_hdl, &solo_motion_trace_ctrl, NULL); - if (solo_dev->disp_hdl.error) { - ret = solo_dev->disp_hdl.error; - goto fail; - } - solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl; - set_bit(V4L2_FL_USE_FH_PRIO, &solo_dev->vfd->flags); - - video_set_drvdata(solo_dev->vfd, solo_dev); - - solo_dev->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - solo_dev->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; - solo_dev->vidq.ops = &solo_video_qops; - solo_dev->vidq.mem_ops = &vb2_dma_contig_memops; - solo_dev->vidq.drv_priv = solo_dev; - solo_dev->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - solo_dev->vidq.gfp_flags = __GFP_DMA32; - solo_dev->vidq.buf_struct_size = sizeof(struct solo_vb2_buf); - solo_dev->vidq.lock = &solo_dev->lock; - ret = vb2_queue_init(&solo_dev->vidq); - if (ret < 0) - goto fail; - - solo_dev->alloc_ctx = vb2_dma_contig_init_ctx(&solo_dev->pdev->dev); - if (IS_ERR(solo_dev->alloc_ctx)) { - dev_err(&solo_dev->pdev->dev, "Can't allocate buffer context"); - return PTR_ERR(solo_dev->alloc_ctx); - } - - /* Cycle all the channels and clear */ - for (i = 0; i < solo_dev->nr_chans; i++) { - solo_v4l2_set_ch(solo_dev, i); - while (erase_off(solo_dev)) - /* Do nothing */; - } - - /* Set the default display channel */ - solo_v4l2_set_ch(solo_dev, 0); - while (erase_off(solo_dev)) - /* Do nothing */; - - ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, nr); - if (ret < 0) - goto fail; - - snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)", - SOLO6X10_NAME, solo_dev->vfd->num); - - dev_info(&solo_dev->pdev->dev, "Display as /dev/video%d with " - "%d inputs (%d extended)\n", solo_dev->vfd->num, - solo_dev->nr_chans, solo_dev->nr_ext); - - return 0; - -fail: - video_device_release(solo_dev->vfd); - vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx); - v4l2_ctrl_handler_free(&solo_dev->disp_hdl); - solo_dev->vfd = NULL; - return ret; -} - -void solo_v4l2_exit(struct solo_dev *solo_dev) -{ - if (solo_dev->vfd == NULL) - return; - - video_unregister_device(solo_dev->vfd); - vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx); - v4l2_ctrl_handler_free(&solo_dev->disp_hdl); - solo_dev->vfd = NULL; -} diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h deleted file mode 100644 index 8964f8be158e..000000000000 --- a/drivers/staging/media/solo6x10/solo6x10.h +++ /dev/null @@ -1,426 +0,0 @@ -/* - * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> - * - * Original author: - * Ben Collins <bcollins@ubuntu.com> - * - * Additional work by: - * John Brooks <john.brooks@bluecherry.net> - * - * 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 __SOLO6X10_H -#define __SOLO6X10_H - -#include <linux/pci.h> -#include <linux/i2c.h> -#include <linux/mutex.h> -#include <linux/list.h> -#include <linux/wait.h> -#include <linux/stringify.h> -#include <linux/io.h> -#include <linux/atomic.h> -#include <linux/slab.h> -#include <linux/videodev2.h> - -#include <media/v4l2-dev.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ctrls.h> -#include <media/videobuf2-core.h> - -#include "solo6x10-regs.h" - -#ifndef PCI_VENDOR_ID_SOFTLOGIC -#define PCI_VENDOR_ID_SOFTLOGIC 0x9413 -#define PCI_DEVICE_ID_SOLO6010 0x6010 -#define PCI_DEVICE_ID_SOLO6110 0x6110 -#endif - -#ifndef PCI_VENDOR_ID_BLUECHERRY -#define PCI_VENDOR_ID_BLUECHERRY 0x1BB3 -/* Neugent Softlogic 6010 based cards */ -#define PCI_DEVICE_ID_NEUSOLO_4 0x4304 -#define PCI_DEVICE_ID_NEUSOLO_9 0x4309 -#define PCI_DEVICE_ID_NEUSOLO_16 0x4310 -/* Bluecherry Softlogic 6010 based cards */ -#define PCI_DEVICE_ID_BC_SOLO_4 0x4E04 -#define PCI_DEVICE_ID_BC_SOLO_9 0x4E09 -#define PCI_DEVICE_ID_BC_SOLO_16 0x4E10 -/* Bluecherry Softlogic 6110 based cards */ -#define PCI_DEVICE_ID_BC_6110_4 0x5304 -#define PCI_DEVICE_ID_BC_6110_8 0x5308 -#define PCI_DEVICE_ID_BC_6110_16 0x5310 -#endif /* Bluecherry */ - -/* Used in pci_device_id, and solo_dev->type */ -#define SOLO_DEV_6010 0 -#define SOLO_DEV_6110 1 - -#define SOLO6X10_NAME "solo6x10" - -#define SOLO_MAX_CHANNELS 16 - -#define SOLO6X10_VERSION "3.0.0" - -/* - * The SOLO6x10 actually has 8 i2c channels, but we only use 2. - * 0 - Techwell chip(s) - * 1 - SAA7128 - */ -#define SOLO_I2C_ADAPTERS 2 -#define SOLO_I2C_TW 0 -#define SOLO_I2C_SAA 1 - -/* DMA Engine setup */ -#define SOLO_NR_P2M 4 -#define SOLO_NR_P2M_DESC 256 -#define SOLO_P2M_DESC_SIZE (SOLO_NR_P2M_DESC * 16) - -/* Encoder standard modes */ -#define SOLO_ENC_MODE_CIF 2 -#define SOLO_ENC_MODE_HD1 1 -#define SOLO_ENC_MODE_D1 9 - -#define SOLO_DEFAULT_QP 3 - -#ifndef V4L2_BUF_FLAG_MOTION_ON -#define V4L2_BUF_FLAG_MOTION_ON 0x10000 -#define V4L2_BUF_FLAG_MOTION_DETECTED 0x20000 -#endif - -#define SOLO_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000) -#define V4L2_CID_MOTION_MODE (SOLO_CID_CUSTOM_BASE+0) -#define V4L2_CID_MOTION_THRESHOLD (SOLO_CID_CUSTOM_BASE+1) -#define V4L2_CID_MOTION_TRACE (SOLO_CID_CUSTOM_BASE+2) -#define V4L2_CID_OSD_TEXT (SOLO_CID_CUSTOM_BASE+3) - -/* - * Motion thresholds are in a table of 64x64 samples, with - * each sample representing 16x16 pixels of the source. In - * effect, 44x30 samples are used for NTSC, and 44x36 for PAL. - * The 5th sample on the 10th row is (10*64)+5 = 645. - * - * Using a 64x64 array will result in a problem on some architectures like - * the powerpc where the size of the argument is limited to 13 bits. - * Since both PAL and NTSC do not use the full table anyway I've chosen - * to limit the array to 45x45 (45*16 = 720, which is the maximum PAL/NTSC - * width). - */ -#define SOLO_MOTION_SZ (45) -struct solo_motion_thresholds { - __u16 thresholds[SOLO_MOTION_SZ][SOLO_MOTION_SZ]; -}; - -#define SOLO_IOC_G_MOTION_THRESHOLDS _IOR('V', BASE_VIDIOC_PRIVATE+0, struct solo_motion_thresholds) -#define SOLO_IOC_S_MOTION_THRESHOLDS _IOW('V', BASE_VIDIOC_PRIVATE+1, struct solo_motion_thresholds) - -enum SOLO_I2C_STATE { - IIC_STATE_IDLE, - IIC_STATE_START, - IIC_STATE_READ, - IIC_STATE_WRITE, - IIC_STATE_STOP -}; - -/* Defined in Table 4-16, Page 68-69 of the 6010 Datasheet */ -struct solo_p2m_desc { - u32 ctrl; - u32 cfg; - u32 dma_addr; - u32 ext_addr; -}; - -struct solo_p2m_dev { - struct mutex mutex; - struct completion completion; - int desc_count; - int desc_idx; - struct solo_p2m_desc *descs; - int error; -}; - -#define OSD_TEXT_MAX 44 - -struct solo_vb2_buf { - struct vb2_buffer vb; - struct list_head list; -}; - -enum solo_enc_types { - SOLO_ENC_TYPE_STD, - SOLO_ENC_TYPE_EXT, -}; - -struct solo_enc_dev { - struct solo_dev *solo_dev; - /* V4L2 Items */ - struct v4l2_ctrl_handler hdl; - struct video_device *vfd; - /* General accounting */ - struct mutex lock; - spinlock_t motion_lock; - u8 ch; - u8 mode, gop, qp, interlaced, interval; - u8 bw_weight; - u16 motion_thresh; - struct solo_motion_thresholds motion_thresholds; - bool motion_global; - bool motion_enabled; - u16 width; - u16 height; - - /* OSD buffers */ - char osd_text[OSD_TEXT_MAX + 1]; - u8 osd_buf[SOLO_EOSD_EXT_SIZE_MAX] - __aligned(4); - - /* VOP stuff */ - unsigned char vop[64]; - int vop_len; - unsigned char jpeg_header[1024]; - int jpeg_len; - - u32 fmt; - enum solo_enc_types type; - u32 sequence; - struct vb2_queue vidq; - struct list_head vidq_active; - int desc_count; - int desc_nelts; - struct solo_p2m_desc *desc_items; - dma_addr_t desc_dma; - spinlock_t av_lock; -}; - -/* The SOLO6x10 PCI Device */ -struct solo_dev { - /* General stuff */ - struct pci_dev *pdev; - int type; - unsigned int time_sync; - unsigned int usec_lsb; - unsigned int clock_mhz; - u8 __iomem *reg_base; - int nr_chans; - int nr_ext; - u32 irq_mask; - u32 motion_mask; - spinlock_t reg_io_lock; - struct v4l2_device v4l2_dev; - - /* tw28xx accounting */ - u8 tw2865, tw2864, tw2815; - u8 tw28_cnt; - - /* i2c related items */ - struct i2c_adapter i2c_adap[SOLO_I2C_ADAPTERS]; - enum SOLO_I2C_STATE i2c_state; - struct mutex i2c_mutex; - int i2c_id; - wait_queue_head_t i2c_wait; - struct i2c_msg *i2c_msg; - unsigned int i2c_msg_num; - unsigned int i2c_msg_ptr; - - /* P2M DMA Engine */ - struct solo_p2m_dev p2m_dev[SOLO_NR_P2M]; - atomic_t p2m_count; - int p2m_jiffies; - unsigned int p2m_timeouts; - - /* V4L2 Display items */ - struct video_device *vfd; - unsigned int erasing; - unsigned int frame_blank; - u8 cur_disp_ch; - wait_queue_head_t disp_thread_wait; - struct v4l2_ctrl_handler disp_hdl; - - /* V4L2 Encoder items */ - struct solo_enc_dev *v4l2_enc[SOLO_MAX_CHANNELS]; - u16 enc_bw_remain; - /* IDX into hw mp4 encoder */ - u8 enc_idx; - - /* Current video settings */ - u32 video_type; - u16 video_hsize, video_vsize; - u16 vout_hstart, vout_vstart; - u16 vin_hstart, vin_vstart; - u8 fps; - - /* JPEG Qp setting */ - spinlock_t jpeg_qp_lock; - u32 jpeg_qp[2]; - - /* Audio components */ - struct snd_card *snd_card; - struct snd_pcm *snd_pcm; - atomic_t snd_users; - int g723_hw_idx; - - /* sysfs stuffs */ - struct device dev; - int sdram_size; - struct bin_attribute sdram_attr; - unsigned int sys_config; - - /* Ring thread */ - struct task_struct *ring_thread; - wait_queue_head_t ring_thread_wait; - - /* VOP_HEADER handling */ - void *vh_buf; - dma_addr_t vh_dma; - int vh_size; - - /* Buffer handling */ - struct vb2_queue vidq; - struct vb2_alloc_ctx *alloc_ctx; - u32 sequence; - struct task_struct *kthread; - struct mutex lock; - spinlock_t slock; - int old_write; - struct list_head vidq_active; -}; - -static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg) -{ - unsigned long flags; - u32 ret; - u16 val; - - spin_lock_irqsave(&solo_dev->reg_io_lock, flags); - - ret = readl(solo_dev->reg_base + reg); - rmb(); - pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val); - rmb(); - - spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags); - - return ret; -} - -static inline void solo_reg_write(struct solo_dev *solo_dev, int reg, - u32 data) -{ - unsigned long flags; - u16 val; - - spin_lock_irqsave(&solo_dev->reg_io_lock, flags); - - writel(data, solo_dev->reg_base + reg); - wmb(); - pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val); - rmb(); - - spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags); -} - -static inline void solo_irq_on(struct solo_dev *dev, u32 mask) -{ - dev->irq_mask |= mask; - solo_reg_write(dev, SOLO_IRQ_MASK, dev->irq_mask); -} - -static inline void solo_irq_off(struct solo_dev *dev, u32 mask) -{ - dev->irq_mask &= ~mask; - solo_reg_write(dev, SOLO_IRQ_MASK, dev->irq_mask); -} - -/* Init/exit routines for subsystems */ -int solo_disp_init(struct solo_dev *solo_dev); -void solo_disp_exit(struct solo_dev *solo_dev); - -int solo_gpio_init(struct solo_dev *solo_dev); -void solo_gpio_exit(struct solo_dev *solo_dev); - -int solo_i2c_init(struct solo_dev *solo_dev); -void solo_i2c_exit(struct solo_dev *solo_dev); - -int solo_p2m_init(struct solo_dev *solo_dev); -void solo_p2m_exit(struct solo_dev *solo_dev); - -int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr); -void solo_v4l2_exit(struct solo_dev *solo_dev); - -int solo_enc_init(struct solo_dev *solo_dev); -void solo_enc_exit(struct solo_dev *solo_dev); - -int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr); -void solo_enc_v4l2_exit(struct solo_dev *solo_dev); - -int solo_g723_init(struct solo_dev *solo_dev); -void solo_g723_exit(struct solo_dev *solo_dev); - -/* ISR's */ -int solo_i2c_isr(struct solo_dev *solo_dev); -void solo_p2m_isr(struct solo_dev *solo_dev, int id); -void solo_p2m_error_isr(struct solo_dev *solo_dev); -void solo_enc_v4l2_isr(struct solo_dev *solo_dev); -void solo_g723_isr(struct solo_dev *solo_dev); -void solo_motion_isr(struct solo_dev *solo_dev); -void solo_video_in_isr(struct solo_dev *solo_dev); - -/* i2c read/write */ -u8 solo_i2c_readbyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off); -void solo_i2c_writebyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off, - u8 data); - -/* P2M DMA */ -int solo_p2m_dma_t(struct solo_dev *solo_dev, int wr, - dma_addr_t dma_addr, u32 ext_addr, u32 size, - int repeat, u32 ext_size); -int solo_p2m_dma(struct solo_dev *solo_dev, int wr, - void *sys_addr, u32 ext_addr, u32 size, - int repeat, u32 ext_size); -void solo_p2m_fill_desc(struct solo_p2m_desc *desc, int wr, - dma_addr_t dma_addr, u32 ext_addr, u32 size, - int repeat, u32 ext_size); -int solo_p2m_dma_desc(struct solo_dev *solo_dev, - struct solo_p2m_desc *desc, dma_addr_t desc_dma, - int desc_cnt); - -/* Global s_std ioctl */ -int solo_set_video_type(struct solo_dev *solo_dev, bool is_50hz); -void solo_update_mode(struct solo_enc_dev *solo_enc); - -/* Set the threshold for motion detection */ -int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val); -int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch, - const struct solo_motion_thresholds *thresholds); -#define SOLO_DEF_MOT_THRESH 0x0300 - -/* Write text on OSD */ -int solo_osd_print(struct solo_enc_dev *solo_enc); - -/* EEPROM commands */ -unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en); -unsigned short solo_eeprom_read(struct solo_dev *solo_dev, int loc); -int solo_eeprom_write(struct solo_dev *solo_dev, int loc, - unsigned short data); - -/* JPEG Qp functions */ -void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch, - unsigned int qp); -int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch); - -#define CHK_FLAGS(v, flags) (((v) & (flags)) == (flags)) - -#endif /* __SOLO6X10_H */ |