summaryrefslogtreecommitdiff
path: root/linux/drivers/media
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-03-25 23:25:35 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-25 23:25:35 -0300
commit22e0e4036603784b9b16618cc8e8fff87b46ff35 (patch)
tree58e1fb22a382d7675cbfb329c1ec8937e6b555aa /linux/drivers/media
parent271ff892e19406f748d58d75cb6bb9d5b2ad7076 (diff)
parentbefdfaef829091b8073e5ab9693242cdb0ecd401 (diff)
downloadmediapointer-dvb-s2-22e0e4036603784b9b16618cc8e8fff87b46ff35.tar.gz
mediapointer-dvb-s2-22e0e4036603784b9b16618cc8e8fff87b46ff35.tar.bz2
merge: http://linuxtv.org/hg/~anttip/ce6230/
From: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'linux/drivers/media')
-rw-r--r--linux/drivers/media/video/gspca/Kconfig9
-rw-r--r--linux/drivers/media/video/gspca/Makefile2
-rw-r--r--linux/drivers/media/video/gspca/sq905c.c328
-rw-r--r--linux/drivers/media/video/gspca/vc032x.c857
-rw-r--r--linux/drivers/media/video/pvrusb2/Makefile6
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-audio.c142
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-audio.h6
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c96
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h (renamed from linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h)21
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c245
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h4
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c5
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h12
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c102
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h34
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c2
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h38
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c626
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c117
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c337
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h51
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c417
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h57
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c121
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c4
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c214
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h7
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c134
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h4
29 files changed, 2004 insertions, 1994 deletions
diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig
index a0f05ef5c..578dc4ffc 100644
--- a/linux/drivers/media/video/gspca/Kconfig
+++ b/linux/drivers/media/video/gspca/Kconfig
@@ -185,6 +185,15 @@ config USB_GSPCA_SQ905
To compile this driver as a module, choose M here: the
module will be called gspca_sq905.
+config USB_GSPCA_SQ905C
+ tristate "SQ Technologies SQ905C based USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the SQ905C chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_sq905c.
+
config USB_GSPCA_STK014
tristate "Syntek DV4000 (STK014) USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
diff --git a/linux/drivers/media/video/gspca/Makefile b/linux/drivers/media/video/gspca/Makefile
index b6ec61185..8a6643e8e 100644
--- a/linux/drivers/media/video/gspca/Makefile
+++ b/linux/drivers/media/video/gspca/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o
obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o
obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o
obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o
+obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o
obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o
obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o
obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o
@@ -43,6 +44,7 @@ gspca_spca506-objs := spca506.o
gspca_spca508-objs := spca508.o
gspca_spca561-objs := spca561.o
gspca_sq905-objs := sq905.o
+gspca_sq905c-objs := sq905c.o
gspca_stk014-objs := stk014.o
gspca_sunplus-objs := sunplus.o
gspca_t613-objs := t613.o
diff --git a/linux/drivers/media/video/gspca/sq905c.c b/linux/drivers/media/video/gspca/sq905c.c
new file mode 100644
index 000000000..0bcb74a1b
--- /dev/null
+++ b/linux/drivers/media/video/gspca/sq905c.c
@@ -0,0 +1,328 @@
+/*
+ * SQ905C subdriver
+ *
+ * Copyright (C) 2009 Theodore Kilgore
+ *
+ * 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
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ *
+ * This driver uses work done in
+ * libgphoto2/camlibs/digigr8, Copyright (C) Theodore Kilgore.
+ *
+ * This driver has also used as a base the sq905c driver
+ * and may contain code fragments from it.
+ */
+
+#define MODULE_NAME "sq905c"
+
+#include <linux/workqueue.h>
+#include "gspca.h"
+
+MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_DESCRIPTION("GSPCA/SQ905C USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeouts, in ms */
+#define SQ905C_CMD_TIMEOUT 500
+#define SQ905C_DATA_TIMEOUT 1000
+
+/* Maximum transfer size to use. */
+#define SQ905C_MAX_TRANSFER 0x8000
+
+#define FRAME_HEADER_LEN 0x50
+
+/* Commands. These go in the "value" slot. */
+#define SQ905C_CLEAR 0xa0 /* clear everything */
+#define SQ905C_CAPTURE_LOW 0xa040 /* Starts capture at 160x120 */
+#define SQ905C_CAPTURE_MED 0x1440 /* Starts capture at 320x240 */
+#define SQ905C_CAPTURE_HI 0x2840 /* Starts capture at 320x240 */
+
+/* For capture, this must go in the "index" slot. */
+#define SQ905C_CAPTURE_INDEX 0x110f
+
+/* Structure to hold all of our device specific stuff */
+struct sd {
+ struct gspca_dev gspca_dev; /* !! must be the first item */
+ const struct v4l2_pix_format *cap_mode;
+ /* Driver stuff */
+ struct work_struct work_struct;
+ struct workqueue_struct *work_thread;
+};
+
+/*
+ * Most of these cameras will do 640x480 and 320x240. 160x120 works
+ * in theory but gives very poor output. Therefore, not supported.
+ * The 0x2770:0x9050 cameras have max resolution of 320x240.
+ */
+static struct v4l2_pix_format sq905c_mode[] = {
+ { 320, 240, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0},
+ { 640, 480, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
+ .bytesperline = 640,
+ .sizeimage = 640 * 480,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0}
+};
+
+/* Send a command to the camera. */
+static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index)
+{
+ int ret;
+
+ ret = usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ USB_REQ_SYNCH_FRAME, /* request */
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ command, index, NULL, 0,
+ SQ905C_CMD_TIMEOUT);
+ if (ret < 0) {
+ PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)",
+ __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* This function is called as a workqueue function and runs whenever the camera
+ * is streaming data. Because it is a workqueue function it is allowed to sleep
+ * so we can use synchronous USB calls. To avoid possible collisions with other
+ * threads attempting to use the camera's USB interface the gspca usb_lock is
+ * used when performing the one USB control operation inside the workqueue,
+ * which tells the camera to close the stream. In practice the only thing
+ * which needs to be protected against is the usb_set_interface call that
+ * gspca makes during stream_off. Otherwise the camera doesn't provide any
+ * controls that the user could try to change.
+ */
+static void sq905c_dostream(struct work_struct *work)
+{
+ struct sd *dev = container_of(work, struct sd, work_struct);
+ struct gspca_dev *gspca_dev = &dev->gspca_dev;
+ struct gspca_frame *frame;
+ int bytes_left; /* bytes remaining in current frame. */
+ int data_len; /* size to use for the next read. */
+ int act_len;
+ int discarding = 0; /* true if we failed to get space for frame. */
+ int packet_type;
+ int ret;
+ u8 *buffer;
+
+ buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
+ if (!buffer) {
+ PDEBUG(D_ERR, "Couldn't allocate USB buffer");
+ goto quit_stream;
+ }
+
+ while (gspca_dev->present && gspca_dev->streaming) {
+ if (!gspca_dev->present)
+ goto quit_stream;
+ /* Request the header, which tells the size to download */
+ ret = usb_bulk_msg(gspca_dev->dev,
+ usb_rcvbulkpipe(gspca_dev->dev, 0x81),
+ buffer, FRAME_HEADER_LEN, &act_len,
+ SQ905C_DATA_TIMEOUT);
+ PDEBUG(D_STREAM,
+ "Got %d bytes out of %d for header",
+ act_len, FRAME_HEADER_LEN);
+ if (ret < 0 || act_len < FRAME_HEADER_LEN)
+ goto quit_stream;
+ /* size is read from 4 bytes starting 0x40, little endian */
+ bytes_left = buffer[0x40]|(buffer[0x41]<<8)|(buffer[0x42]<<16)
+ |(buffer[0x43]<<24);
+ PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left);
+ /* We keep the header. It has other information, too. */
+ packet_type = FIRST_PACKET;
+ frame = gspca_get_i_frame(gspca_dev);
+ if (frame && !discarding) {
+ gspca_frame_add(gspca_dev, packet_type,
+ frame, buffer, FRAME_HEADER_LEN);
+ } else
+ discarding = 1;
+ while (bytes_left > 0) {
+ data_len = bytes_left > SQ905C_MAX_TRANSFER ?
+ SQ905C_MAX_TRANSFER : bytes_left;
+ if (!gspca_dev->present)
+ goto quit_stream;
+ ret = usb_bulk_msg(gspca_dev->dev,
+ usb_rcvbulkpipe(gspca_dev->dev, 0x81),
+ buffer, data_len, &act_len,
+ SQ905C_DATA_TIMEOUT);
+ if (ret < 0 || act_len < data_len)
+ goto quit_stream;
+ PDEBUG(D_STREAM,
+ "Got %d bytes out of %d for frame",
+ data_len, bytes_left);
+ bytes_left -= data_len;
+ if (bytes_left == 0)
+ packet_type = LAST_PACKET;
+ else
+ packet_type = INTER_PACKET;
+ frame = gspca_get_i_frame(gspca_dev);
+ if (frame && !discarding)
+ gspca_frame_add(gspca_dev, packet_type,
+ frame, buffer, data_len);
+ else
+ discarding = 1;
+ }
+ }
+quit_stream:
+ mutex_lock(&gspca_dev->usb_lock);
+ if (gspca_dev->present)
+ sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
+ mutex_unlock(&gspca_dev->usb_lock);
+ kfree(buffer);
+}
+
+/* This function is called at probe time just before sd_init */
+static int sd_config(struct gspca_dev *gspca_dev,
+ const struct usb_device_id *id)
+{
+ struct cam *cam = &gspca_dev->cam;
+ struct sd *dev = (struct sd *) gspca_dev;
+
+ PDEBUG(D_PROBE,
+ "SQ9050 camera detected"
+ " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+ cam->cam_mode = sq905c_mode;
+ cam->nmodes = 2;
+ if (id->idProduct == 0x9050)
+ cam->nmodes = 1;
+ /* We don't use the buffer gspca allocates so make it small. */
+ cam->bulk_size = 32;
+ INIT_WORK(&dev->work_struct, sq905c_dostream);
+ return 0;
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+ struct sd *dev = (struct sd *) gspca_dev;
+
+ /* wait for the work queue to terminate */
+ mutex_unlock(&gspca_dev->usb_lock);
+ /* This waits for sq905c_dostream to finish */
+ destroy_workqueue(dev->work_thread);
+ dev->work_thread = NULL;
+ mutex_lock(&gspca_dev->usb_lock);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+ int ret;
+
+ /* connect to the camera and reset it. */
+ ret = sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
+ return ret;
+}
+
+/* Set up for getting frames. */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+ struct sd *dev = (struct sd *) gspca_dev;
+ int ret;
+
+ dev->cap_mode = gspca_dev->cam.cam_mode;
+ /* "Open the shutter" and set size, to start capture */
+ switch (gspca_dev->width) {
+ case 640:
+ PDEBUG(D_STREAM, "Start streaming at high resolution");
+ dev->cap_mode++;
+ ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_HI,
+ SQ905C_CAPTURE_INDEX);
+ break;
+ default: /* 320 */
+ PDEBUG(D_STREAM, "Start streaming at medium resolution");
+ ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_MED,
+ SQ905C_CAPTURE_INDEX);
+ }
+
+ if (ret < 0) {
+ PDEBUG(D_ERR, "Start streaming command failed");
+ return ret;
+ }
+ /* Start the workqueue function to do the streaming */
+ dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
+ queue_work(dev->work_thread, &dev->work_struct);
+
+ return 0;
+}
+
+/* Table of supported USB devices */
+static const __devinitdata struct usb_device_id device_table[] = {
+ {USB_DEVICE(0x2770, 0x905c)},
+ {USB_DEVICE(0x2770, 0x9050)},
+ {USB_DEVICE(0x2770, 0x913d)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+ .name = MODULE_NAME,
+ .config = sd_config,
+ .init = sd_init,
+ .start = sd_start,
+ .stop0 = sd_stop0,
+};
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return gspca_dev_probe(intf, id,
+ &sd_desc,
+ sizeof(struct sd),
+ THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+ .name = MODULE_NAME,
+ .id_table = device_table,
+ .probe = sd_probe,
+ .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+ int ret;
+
+ ret = usb_register(&sd_driver);
+ if (ret < 0)
+ return ret;
+ PDEBUG(D_PROBE, "registered");
+ return 0;
+}
+
+static void __exit sd_mod_exit(void)
+{
+ usb_deregister(&sd_driver);
+ PDEBUG(D_PROBE, "deregistered");
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c
index 581cbff38..772d18e70 100644
--- a/linux/drivers/media/video/gspca/vc032x.c
+++ b/linux/drivers/media/video/gspca/vc032x.c
@@ -37,18 +37,21 @@ struct sd {
__u8 lightfreq;
__u8 sharpness;
+ u8 image_offset;
+
char bridge;
#define BRIDGE_VC0321 0
#define BRIDGE_VC0323 1
char sensor;
#define SENSOR_HV7131R 0
#define SENSOR_MI0360 1
-#define SENSOR_MI1320 2
-#define SENSOR_MI1310_SOC 3
-#define SENSOR_OV7660 4
-#define SENSOR_OV7670 5
-#define SENSOR_PO1200 6
-#define SENSOR_PO3130NC 7
+#define SENSOR_MI1310_SOC 2
+#define SENSOR_MI1320 3
+#define SENSOR_MI1320_SOC 4
+#define SENSOR_OV7660 5
+#define SENSOR_OV7670 6
+#define SENSOR_PO1200 7
+#define SENSOR_PO3130NC 8
};
/* V4L2 controls supported by the driver */
@@ -149,13 +152,50 @@ static const struct v4l2_pix_format vc0323_mode[] = {
.sizeimage = 640 * 480 * 3 / 8 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 0},
- {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi1310_soc only */
+ {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi13x0_soc only */
.bytesperline = 1280,
.sizeimage = 1280 * 1024 * 1 / 4 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 2},
};
-
+static const struct v4l2_pix_format bi_mode[] = {
+/*fixme: jeg does not work
+ {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240 * 3 / 8 + 590,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 5},
+*/
+ {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240 * 2,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 4},
+/*
+ {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+ .bytesperline = 640,
+ .sizeimage = 640 * 480 * 3 / 8 + 590,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 3},
+*/
+ {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+ .bytesperline = 640,
+ .sizeimage = 640 * 480 * 2,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 2},
+/*
+ {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+ .bytesperline = 1280,
+ .sizeimage = 1280 * 1024 * 1 / 4 + 590,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 1},
+*/
+ {1280, 1024, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+ .bytesperline = 1280,
+ .sizeimage = 1280 * 1024 * 2,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0},
+};
static const struct v4l2_pix_format svga_mode[] = {
{800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 800,
@@ -891,6 +931,722 @@ static const __u8 mi1320_initQVGA_data[][4] = {
{}
};
+static const u8 mi1320_soc_InitVGA[][4] = {
+ {0xb3, 0x01, 0x01, 0xcc},
+ {0xb0, 0x03, 0x19, 0xcc},
+ {0xb0, 0x04, 0x02, 0xcc},
+ {0x00, 0x00, 0x30, 0xdd},
+ {0xb3, 0x00, 0x64, 0xcc},
+ {0xb3, 0x00, 0x67, 0xcc},
+ {0xb3, 0x05, 0x01, 0xcc},
+ {0xb3, 0x06, 0x01, 0xcc},
+ {0xb3, 0x08, 0x01, 0xcc},
+ {0xb3, 0x09, 0x0c, 0xcc},
+ {0xb3, 0x34, 0x02, 0xcc},
+ {0xb3, 0x35, 0xc8, 0xcc},
+ {0xb3, 0x02, 0x00, 0xcc},
+ {0xb3, 0x03, 0x0a, 0xcc},
+ {0xb3, 0x04, 0x05, 0xcc},
+ {0xb3, 0x20, 0x00, 0xcc},
+ {0xb3, 0x21, 0x00, 0xcc},
+ {0xb3, 0x22, 0x01, 0xcc},
+ {0xb3, 0x23, 0xe0, 0xcc},
+ {0xb3, 0x14, 0x00, 0xcc},
+ {0xb3, 0x15, 0x00, 0xcc},
+ {0xb3, 0x16, 0x02, 0xcc},
+ {0xb3, 0x17, 0x7f, 0xcc},
+ {0xb3, 0x00, 0x67, 0xcc},
+ {0xb8, 0x00, 0x00, 0xcc},
+ {0xbc, 0x00, 0x71, 0xcc},
+ {0xbc, 0x01, 0x01, 0xcc},
+ {0xb3, 0x5c, 0x01, 0xcc},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x00, 0x00, 0x10, 0xdd},
+ {0xc8, 0x00, 0x00, 0xbb},
+ {0x00, 0x00, 0x30, 0xdd},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x00, 0x00, 0x10, 0xdd},
+ {0x07, 0x00, 0xe0, 0xbb},
+ {0x08, 0x00, 0x0b, 0xbb},
+ {0x21, 0x00, 0x0c, 0xbb},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0xbf, 0xc0, 0x26, 0xcc},
+ {0xbf, 0xc1, 0x02, 0xcc},
+ {0xbf, 0xcc, 0x04, 0xcc},
+ {0xb3, 0x01, 0x41, 0xcc},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x05, 0x01, 0x78, 0xbb},
+ {0x06, 0x00, 0x11, 0xbb},
+ {0x07, 0x01, 0x42, 0xbb},
+ {0x08, 0x00, 0x11, 0xbb},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0x21, 0x80, 0x00, 0xbb},
+ {0x22, 0x0d, 0x0f, 0xbb},
+ {0x24, 0x80, 0x00, 0xbb},
+ {0x59, 0x00, 0xff, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x39, 0x03, 0xca, 0xbb},
+ {0x3a, 0x06, 0x80, 0xbb},
+ {0x3b, 0x01, 0x52, 0xbb},
+ {0x3c, 0x05, 0x40, 0xbb},
+ {0x57, 0x01, 0x9c, 0xbb},
+ {0x58, 0x01, 0xee, 0xbb},
+ {0x59, 0x00, 0xf0, 0xbb},
+ {0x5a, 0x01, 0x20, 0xbb},
+ {0x5c, 0x1d, 0x17, 0xbb},
+ {0x5d, 0x22, 0x1c, 0xbb},
+ {0x64, 0x1e, 0x1c, 0xbb},
+ {0x5b, 0x00, 0x00, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x22, 0xa0, 0x78, 0xbb},
+ {0x23, 0xa0, 0x78, 0xbb},
+ {0x24, 0x7f, 0x00, 0xbb},
+ {0x28, 0xea, 0x02, 0xbb},
+ {0x29, 0x86, 0x7a, 0xbb},
+ {0x5e, 0x52, 0x4c, 0xbb},
+ {0x5f, 0x20, 0x24, 0xbb},
+ {0x60, 0x00, 0x02, 0xbb},
+ {0x02, 0x00, 0xee, 0xbb},
+ {0x03, 0x39, 0x23, 0xbb},
+ {0x04, 0x07, 0x24, 0xbb},
+ {0x09, 0x00, 0xc0, 0xbb},
+ {0x0a, 0x00, 0x79, 0xbb},
+ {0x0b, 0x00, 0x04, 0xbb},
+ {0x0c, 0x00, 0x5c, 0xbb},
+ {0x0d, 0x00, 0xd9, 0xbb},
+ {0x0e, 0x00, 0x53, 0xbb},
+ {0x0f, 0x00, 0x21, 0xbb},
+ {0x10, 0x00, 0xa4, 0xbb},
+ {0x11, 0x00, 0xe5, 0xbb},
+ {0x15, 0x00, 0x00, 0xbb},
+ {0x16, 0x00, 0x00, 0xbb},
+ {0x17, 0x00, 0x00, 0xbb},
+ {0x18, 0x00, 0x00, 0xbb},
+ {0x19, 0x00, 0x00, 0xbb},
+ {0x1a, 0x00, 0x00, 0xbb},
+ {0x1b, 0x00, 0x00, 0xbb},
+ {0x1c, 0x00, 0x00, 0xbb},
+ {0x1d, 0x00, 0x00, 0xbb},
+ {0x1e, 0x00, 0x00, 0xbb},
+ {0xf0, 0x00, 0x01, 0xbb},
+ {0x06, 0xe0, 0x0e, 0xbb},
+ {0x06, 0x60, 0x0e, 0xbb},
+ {0xb3, 0x5c, 0x01, 0xcc},
+ {}
+};
+static const u8 mi1320_soc_InitVGA_JPG[][4] = {
+ {0xb3, 0x01, 0x01, 0xcc},
+ {0xb0, 0x03, 0x19, 0xcc},
+ {0xb0, 0x04, 0x02, 0xcc},
+ {0x00, 0x00, 0x30, 0xdd},
+ {0xb3, 0x00, 0x64, 0xcc},
+ {0xb3, 0x00, 0x67, 0xcc},
+ {0xb3, 0x05, 0x01, 0xcc},
+ {0xb3, 0x06, 0x01, 0xcc},
+ {0xb3, 0x08, 0x01, 0xcc},
+ {0xb3, 0x09, 0x0c, 0xcc},
+ {0xb3, 0x34, 0x02, 0xcc},
+ {0xb3, 0x35, 0xc8, 0xcc},
+ {0xb3, 0x02, 0x00, 0xcc},
+ {0xb3, 0x03, 0x0a, 0xcc},
+ {0xb3, 0x04, 0x05, 0xcc},
+ {0xb3, 0x20, 0x00, 0xcc},
+ {0xb3, 0x21, 0x00, 0xcc},
+ {0xb3, 0x22, 0x01, 0xcc},
+ {0xb3, 0x23, 0xe0, 0xcc},
+ {0xb3, 0x14, 0x00, 0xcc},
+ {0xb3, 0x15, 0x00, 0xcc},
+ {0xb3, 0x16, 0x02, 0xcc},
+ {0xb3, 0x17, 0x7f, 0xcc},
+ {0xb3, 0x00, 0x67, 0xcc},
+ {0xb8, 0x00, 0x00, 0xcc},
+ {0xbc, 0x00, 0x71, 0xcc},
+ {0xbc, 0x01, 0x01, 0xcc},
+ {0xb3, 0x5c, 0x01, 0xcc},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x00, 0x00, 0x10, 0xdd},
+ {0xc8, 0x00, 0x00, 0xbb},
+ {0x00, 0x00, 0x30, 0xdd},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x00, 0x00, 0x10, 0xdd},
+ {0x07, 0x00, 0xe0, 0xbb},
+ {0x08, 0x00, 0x0b, 0xbb},
+ {0x21, 0x00, 0x0c, 0xbb},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0xb6, 0x00, 0x00, 0xcc},
+ {0xb6, 0x03, 0x02, 0xcc},
+ {0xb6, 0x02, 0x80, 0xcc},
+ {0xb6, 0x05, 0x01, 0xcc},
+ {0xb6, 0x04, 0xe0, 0xcc},
+ {0xb6, 0x12, 0xf8, 0xcc},
+ {0xb6, 0x13, 0x05, 0xcc},
+ {0xb6, 0x18, 0x02, 0xcc},
+ {0xb6, 0x17, 0x58, 0xcc},
+ {0xb6, 0x16, 0x00, 0xcc},
+ {0xb6, 0x22, 0x12, 0xcc},
+ {0xb6, 0x23, 0x0b, 0xcc},
+ {0xbf, 0xc0, 0x39, 0xcc},
+ {0xbf, 0xc1, 0x04, 0xcc},
+ {0xbf, 0xcc, 0x00, 0xcc},
+ {0xb3, 0x01, 0x41, 0xcc},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x05, 0x01, 0x78, 0xbb},
+ {0x06, 0x00, 0x11, 0xbb},
+ {0x07, 0x01, 0x42, 0xbb},
+ {0x08, 0x00, 0x11, 0xbb},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0x21, 0x80, 0x00, 0xbb},
+ {0x22, 0x0d, 0x0f, 0xbb},
+ {0x24, 0x80, 0x00, 0xbb},
+ {0x59, 0x00, 0xff, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x39, 0x03, 0xca, 0xbb},
+ {0x3a, 0x06, 0x80, 0xbb},
+ {0x3b, 0x01, 0x52, 0xbb},
+ {0x3c, 0x05, 0x40, 0xbb},
+ {0x57, 0x01, 0x9c, 0xbb},
+ {0x58, 0x01, 0xee, 0xbb},
+ {0x59, 0x00, 0xf0, 0xbb},
+ {0x5a, 0x01, 0x20, 0xbb},
+ {0x5c, 0x1d, 0x17, 0xbb},
+ {0x5d, 0x22, 0x1c, 0xbb},
+ {0x64, 0x1e, 0x1c, 0xbb},
+ {0x5b, 0x00, 0x00, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x22, 0xa0, 0x78, 0xbb},
+ {0x23, 0xa0, 0x78, 0xbb},
+ {0x24, 0x7f, 0x00, 0xbb},
+ {0x28, 0xea, 0x02, 0xbb},
+ {0x29, 0x86, 0x7a, 0xbb},
+ {0x5e, 0x52, 0x4c, 0xbb},
+ {0x5f, 0x20, 0x24, 0xbb},
+ {0x60, 0x00, 0x02, 0xbb},
+ {0x02, 0x00, 0xee, 0xbb},
+ {0x03, 0x39, 0x23, 0xbb},
+ {0x04, 0x07, 0x24, 0xbb},
+ {0x09, 0x00, 0xc0, 0xbb},
+ {0x0a, 0x00, 0x79, 0xbb},
+ {0x0b, 0x00, 0x04, 0xbb},
+ {0x0c, 0x00, 0x5c, 0xbb},
+ {0x0d, 0x00, 0xd9, 0xbb},
+ {0x0e, 0x00, 0x53, 0xbb},
+ {0x0f, 0x00, 0x21, 0xbb},
+ {0x10, 0x00, 0xa4, 0xbb},
+ {0x11, 0x00, 0xe5, 0xbb},
+ {0x15, 0x00, 0x00, 0xbb},
+ {0x16, 0x00, 0x00, 0xbb},
+ {0x17, 0x00, 0x00, 0xbb},
+ {0x18, 0x00, 0x00, 0xbb},
+ {0x19, 0x00, 0x00, 0xbb},
+ {0x1a, 0x00, 0x00, 0xbb},
+ {0x1b, 0x00, 0x00, 0xbb},
+ {0x1c, 0x00, 0x00, 0xbb},
+ {0x1d, 0x00, 0x00, 0xbb},
+ {0x1e, 0x00, 0x00, 0xbb},
+ {0xf0, 0x00, 0x01, 0xbb},
+ {0x06, 0xe0, 0x0e, 0xbb},
+ {0x06, 0x60, 0x0e, 0xbb},
+ {0xb3, 0x5c, 0x01, 0xcc},
+ {}
+};
+static const u8 mi1320_soc_InitQVGA[][4] = {
+ {0xb3, 0x01, 0x01, 0xcc},
+ {0xb0, 0x03, 0x19, 0xcc},
+ {0xb0, 0x04, 0x02, 0xcc},
+ {0x00, 0x00, 0x30, 0xdd},
+ {0xb3, 0x00, 0x64, 0xcc},
+ {0xb3, 0x00, 0x67, 0xcc},
+ {0xb3, 0x05, 0x01, 0xcc},
+ {0xb3, 0x06, 0x01, 0xcc},
+ {0xb3, 0x08, 0x01, 0xcc},
+ {0xb3, 0x09, 0x0c, 0xcc},
+ {0xb3, 0x34, 0x02, 0xcc},
+ {0xb3, 0x35, 0xc8, 0xcc},
+ {0xb3, 0x02, 0x00, 0xcc},
+ {0xb3, 0x03, 0x0a, 0xcc},
+ {0xb3, 0x04, 0x05, 0xcc},
+ {0xb3, 0x20, 0x00, 0xcc},
+ {0xb3, 0x21, 0x00, 0xcc},
+ {0xb3, 0x22, 0x01, 0xcc},
+ {0xb3, 0x23, 0xe0, 0xcc},
+ {0xb3, 0x14, 0x00, 0xcc},
+ {0xb3, 0x15, 0x00, 0xcc},
+ {0xb3, 0x16, 0x02, 0xcc},
+ {0xb3, 0x17, 0x7f, 0xcc},
+ {0xb3, 0x00, 0x67, 0xcc},
+ {0xb8, 0x00, 0x00, 0xcc},
+ {0xbc, 0x00, 0xd1, 0xcc},
+ {0xbc, 0x01, 0x01, 0xcc},
+ {0xb3, 0x5c, 0x01, 0xcc},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x00, 0x00, 0x10, 0xdd},
+ {0xc8, 0x00, 0x00, 0xbb},
+ {0x00, 0x00, 0x30, 0xdd},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x00, 0x00, 0x10, 0xdd},
+ {0x07, 0x00, 0xe0, 0xbb},
+ {0x08, 0x00, 0x0b, 0xbb},
+ {0x21, 0x00, 0x0c, 0xbb},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0xbf, 0xc0, 0x26, 0xcc},
+ {0xbf, 0xc1, 0x02, 0xcc},
+ {0xbf, 0xcc, 0x04, 0xcc},
+ {0xbc, 0x02, 0x18, 0xcc},
+ {0xbc, 0x03, 0x50, 0xcc},
+ {0xbc, 0x04, 0x18, 0xcc},
+ {0xbc, 0x05, 0x00, 0xcc},
+ {0xbc, 0x06, 0x00, 0xcc},
+ {0xbc, 0x08, 0x30, 0xcc},
+ {0xbc, 0x09, 0x40, 0xcc},
+ {0xbc, 0x0a, 0x10, 0xcc},
+ {0xbc, 0x0b, 0x00, 0xcc},
+ {0xbc, 0x0c, 0x00, 0xcc},
+ {0xb3, 0x01, 0x41, 0xcc},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x05, 0x01, 0x78, 0xbb},
+ {0x06, 0x00, 0x11, 0xbb},
+ {0x07, 0x01, 0x42, 0xbb},
+ {0x08, 0x00, 0x11, 0xbb},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0x21, 0x80, 0x00, 0xbb},
+ {0x22, 0x0d, 0x0f, 0xbb},
+ {0x24, 0x80, 0x00, 0xbb},
+ {0x59, 0x00, 0xff, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x39, 0x03, 0xca, 0xbb},
+ {0x3a, 0x06, 0x80, 0xbb},
+ {0x3b, 0x01, 0x52, 0xbb},
+ {0x3c, 0x05, 0x40, 0xbb},
+ {0x57, 0x01, 0x9c, 0xbb},
+ {0x58, 0x01, 0xee, 0xbb},
+ {0x59, 0x00, 0xf0, 0xbb},
+ {0x5a, 0x01, 0x20, 0xbb},
+ {0x5c, 0x1d, 0x17, 0xbb},
+ {0x5d, 0x22, 0x1c, 0xbb},
+ {0x64, 0x1e, 0x1c, 0xbb},
+ {0x5b, 0x00, 0x00, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x22, 0xa0, 0x78, 0xbb},
+ {0x23, 0xa0, 0x78, 0xbb},
+ {0x24, 0x7f, 0x00, 0xbb},
+ {0x28, 0xea, 0x02, 0xbb},
+ {0x29, 0x86, 0x7a, 0xbb},
+ {0x5e, 0x52, 0x4c, 0xbb},
+ {0x5f, 0x20, 0x24, 0xbb},
+ {0x60, 0x00, 0x02, 0xbb},
+ {0x02, 0x00, 0xee, 0xbb},
+ {0x03, 0x39, 0x23, 0xbb},
+ {0x04, 0x07, 0x24, 0xbb},
+ {0x09, 0x00, 0xc0, 0xbb},
+ {0x0a, 0x00, 0x79, 0xbb},
+ {0x0b, 0x00, 0x04, 0xbb},
+ {0x0c, 0x00, 0x5c, 0xbb},
+ {0x0d, 0x00, 0xd9, 0xbb},
+ {0x0e, 0x00, 0x53, 0xbb},
+ {0x0f, 0x00, 0x21, 0xbb},
+ {0x10, 0x00, 0xa4, 0xbb},
+ {0x11, 0x00, 0xe5, 0xbb},
+ {0x15, 0x00, 0x00, 0xbb},
+ {0x16, 0x00, 0x00, 0xbb},
+ {0x17, 0x00, 0x00, 0xbb},
+ {0x18, 0x00, 0x00, 0xbb},
+ {0x19, 0x00, 0x00, 0xbb},
+ {0x1a, 0x00, 0x00, 0xbb},
+ {0x1b, 0x00, 0x00, 0xbb},
+ {0x1c, 0x00, 0x00, 0xbb},
+ {0x1d, 0x00, 0x00, 0xbb},
+ {0x1e, 0x00, 0x00, 0xbb},
+ {0xf0, 0x00, 0x01, 0xbb},
+ {0x06, 0xe0, 0x0e, 0xbb},
+ {0x06, 0x60, 0x0e, 0xbb},
+ {0xb3, 0x5c, 0x01, 0xcc},
+ {}
+};
+static const u8 mi1320_soc_InitQVGA_JPG[][4] = {
+ {0xb3, 0x01, 0x01, 0xcc},
+ {0xb0, 0x03, 0x19, 0xcc},
+ {0xb0, 0x04, 0x02, 0xcc},
+ {0x00, 0x00, 0x30, 0xdd},
+ {0xb3, 0x00, 0x64, 0xcc},
+ {0xb3, 0x00, 0x67, 0xcc},
+ {0xb3, 0x05, 0x01, 0xcc},
+ {0xb3, 0x06, 0x01, 0xcc},
+ {0xb3, 0x08, 0x01, 0xcc},
+ {0xb3, 0x09, 0x0c, 0xcc},
+ {0xb3, 0x34, 0x02, 0xcc},
+ {0xb3, 0x35, 0xc8, 0xcc},
+ {0xb3, 0x02, 0x00, 0xcc},
+ {0xb3, 0x03, 0x0a, 0xcc},
+ {0xb3, 0x04, 0x05, 0xcc},
+ {0xb3, 0x20, 0x00, 0xcc},
+ {0xb3, 0x21, 0x00, 0xcc},
+ {0xb3, 0x22, 0x01, 0xcc},
+ {0xb3, 0x23, 0xe0, 0xcc},
+ {0xb3, 0x14, 0x00, 0xcc},
+ {0xb3, 0x15, 0x00, 0xcc},
+ {0xb3, 0x16, 0x02, 0xcc},
+ {0xb3, 0x17, 0x7f, 0xcc},
+ {0xb3, 0x00, 0x67, 0xcc},
+ {0xb8, 0x00, 0x00, 0xcc},
+ {0xbc, 0x00, 0xd1, 0xcc},
+ {0xbc, 0x01, 0x01, 0xcc},
+ {0xb3, 0x5c, 0x01, 0xcc},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x00, 0x00, 0x10, 0xdd},
+ {0xc8, 0x00, 0x00, 0xbb},
+ {0x00, 0x00, 0x30, 0xdd},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x00, 0x00, 0x10, 0xdd},
+ {0x07, 0x00, 0xe0, 0xbb},
+ {0x08, 0x00, 0x0b, 0xbb},
+ {0x21, 0x00, 0x0c, 0xbb},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0xb6, 0x00, 0x00, 0xcc},
+ {0xb6, 0x03, 0x01, 0xcc},
+ {0xb6, 0x02, 0x40, 0xcc},
+ {0xb6, 0x05, 0x00, 0xcc},
+ {0xb6, 0x04, 0xf0, 0xcc},
+ {0xb6, 0x12, 0xf8, 0xcc},
+ {0xb6, 0x13, 0x05, 0xcc},
+ {0xb6, 0x18, 0x00, 0xcc},
+ {0xb6, 0x17, 0x96, 0xcc},
+ {0xb6, 0x16, 0x00, 0xcc},
+ {0xb6, 0x22, 0x12, 0xcc},
+ {0xb6, 0x23, 0x0b, 0xcc},
+ {0xbf, 0xc0, 0x39, 0xcc},
+ {0xbf, 0xc1, 0x04, 0xcc},
+ {0xbf, 0xcc, 0x00, 0xcc},
+ {0xbc, 0x02, 0x18, 0xcc},
+ {0xbc, 0x03, 0x50, 0xcc},
+ {0xbc, 0x04, 0x18, 0xcc},
+ {0xbc, 0x05, 0x00, 0xcc},
+ {0xbc, 0x06, 0x00, 0xcc},
+ {0xbc, 0x08, 0x30, 0xcc},
+ {0xbc, 0x09, 0x40, 0xcc},
+ {0xbc, 0x0a, 0x10, 0xcc},
+ {0xbc, 0x0b, 0x00, 0xcc},
+ {0xbc, 0x0c, 0x00, 0xcc},
+ {0xb3, 0x01, 0x41, 0xcc},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x05, 0x01, 0x78, 0xbb},
+ {0x06, 0x00, 0x11, 0xbb},
+ {0x07, 0x01, 0x42, 0xbb},
+ {0x08, 0x00, 0x11, 0xbb},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0x21, 0x80, 0x00, 0xbb},
+ {0x22, 0x0d, 0x0f, 0xbb},
+ {0x24, 0x80, 0x00, 0xbb},
+ {0x59, 0x00, 0xff, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x39, 0x03, 0xca, 0xbb},
+ {0x3a, 0x06, 0x80, 0xbb},
+ {0x3b, 0x01, 0x52, 0xbb},
+ {0x3c, 0x05, 0x40, 0xbb},
+ {0x57, 0x01, 0x9c, 0xbb},
+ {0x58, 0x01, 0xee, 0xbb},
+ {0x59, 0x00, 0xf0, 0xbb},
+ {0x5a, 0x01, 0x20, 0xbb},
+ {0x5c, 0x1d, 0x17, 0xbb},
+ {0x5d, 0x22, 0x1c, 0xbb},
+ {0x64, 0x1e, 0x1c, 0xbb},
+ {0x5b, 0x00, 0x00, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x22, 0xa0, 0x78, 0xbb},
+ {0x23, 0xa0, 0x78, 0xbb},
+ {0x24, 0x7f, 0x00, 0xbb},
+ {0x28, 0xea, 0x02, 0xbb},
+ {0x29, 0x86, 0x7a, 0xbb},
+ {0x5e, 0x52, 0x4c, 0xbb},
+ {0x5f, 0x20, 0x24, 0xbb},
+ {0x60, 0x00, 0x02, 0xbb},
+ {0x02, 0x00, 0xee, 0xbb},
+ {0x03, 0x39, 0x23, 0xbb},
+ {0x04, 0x07, 0x24, 0xbb},
+ {0x09, 0x00, 0xc0, 0xbb},
+ {0x0a, 0x00, 0x79, 0xbb},
+ {0x0b, 0x00, 0x04, 0xbb},
+ {0x0c, 0x00, 0x5c, 0xbb},
+ {0x0d, 0x00, 0xd9, 0xbb},
+ {0x0e, 0x00, 0x53, 0xbb},
+ {0x0f, 0x00, 0x21, 0xbb},
+ {0x10, 0x00, 0xa4, 0xbb},
+ {0x11, 0x00, 0xe5, 0xbb},
+ {0x15, 0x00, 0x00, 0xbb},
+ {0x16, 0x00, 0x00, 0xbb},
+ {0x17, 0x00, 0x00, 0xbb},
+ {0x18, 0x00, 0x00, 0xbb},
+ {0x19, 0x00, 0x00, 0xbb},
+ {0x1a, 0x00, 0x00, 0xbb},
+ {0x1b, 0x00, 0x00, 0xbb},
+ {0x1c, 0x00, 0x00, 0xbb},
+ {0x1d, 0x00, 0x00, 0xbb},
+ {0x1e, 0x00, 0x00, 0xbb},
+ {0xf0, 0x00, 0x01, 0xbb},
+ {0x06, 0xe0, 0x0e, 0xbb},
+ {0x06, 0x60, 0x0e, 0xbb},
+ {0xb3, 0x5c, 0x01, 0xcc},
+ {}
+};
+static const u8 mi1320_soc_InitSXGA_JPG[][4] = {
+ {0xb3, 0x01, 0x01, 0xcc},
+ {0xb0, 0x03, 0x19, 0xcc},
+ {0xb0, 0x04, 0x02, 0xcc},
+ {0x00, 0x00, 0x33, 0xdd},
+ {0xb3, 0x00, 0x64, 0xcc},
+ {0xb3, 0x00, 0x67, 0xcc},
+ {0xb3, 0x05, 0x00, 0xcc},
+ {0xb3, 0x06, 0x00, 0xcc},
+ {0xb3, 0x08, 0x01, 0xcc},
+ {0xb3, 0x09, 0x0c, 0xcc},
+ {0xb3, 0x34, 0x02, 0xcc},
+ {0xb3, 0x35, 0xc8, 0xcc},
+ {0xb3, 0x02, 0x00, 0xcc},
+ {0xb3, 0x03, 0x0a, 0xcc},
+ {0xb3, 0x04, 0x05, 0xcc},
+ {0xb3, 0x20, 0x00, 0xcc},
+ {0xb3, 0x21, 0x00, 0xcc},
+ {0xb3, 0x22, 0x04, 0xcc},
+ {0xb3, 0x23, 0x00, 0xcc},
+ {0xb3, 0x14, 0x00, 0xcc},
+ {0xb3, 0x15, 0x00, 0xcc},
+ {0xb3, 0x16, 0x04, 0xcc},
+ {0xb3, 0x17, 0xff, 0xcc},
+ {0xb3, 0x00, 0x67, 0xcc},
+ {0xbc, 0x00, 0x71, 0xcc},
+ {0xbc, 0x01, 0x01, 0xcc},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x00, 0x00, 0x30, 0xdd},
+ {0xc8, 0x9f, 0x0b, 0xbb},
+ {0x00, 0x00, 0x20, 0xdd},
+ {0x5b, 0x00, 0x01, 0xbb},
+ {0x00, 0x00, 0x20, 0xdd},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x00, 0x00, 0x30, 0xdd},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0x00, 0x00, 0x20, 0xdd},
+ {0xb6, 0x00, 0x00, 0xcc},
+ {0xb6, 0x03, 0x05, 0xcc},
+ {0xb6, 0x02, 0x00, 0xcc},
+ {0xb6, 0x05, 0x04, 0xcc},
+ {0xb6, 0x04, 0x00, 0xcc},
+ {0xb6, 0x12, 0xf8, 0xcc},
+ {0xb6, 0x13, 0x29, 0xcc},
+ {0xb6, 0x18, 0x0a, 0xcc},
+ {0xb6, 0x17, 0x00, 0xcc},
+ {0xb6, 0x16, 0x00, 0xcc},
+ {0xb6, 0x22, 0x12, 0xcc},
+ {0xb6, 0x23, 0x0b, 0xcc},
+ {0xbf, 0xc0, 0x39, 0xcc},
+ {0xbf, 0xc1, 0x04, 0xcc},
+ {0xbf, 0xcc, 0x00, 0xcc},
+ {0xb3, 0x5c, 0x01, 0xcc},
+ {0xb3, 0x01, 0x41, 0xcc},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x05, 0x01, 0x78, 0xbb},
+ {0x06, 0x00, 0x11, 0xbb},
+ {0x07, 0x01, 0x42, 0xbb},
+ {0x08, 0x00, 0x11, 0xbb},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0x21, 0x80, 0x00, 0xbb},
+ {0x22, 0x0d, 0x0f, 0xbb},
+ {0x24, 0x80, 0x00, 0xbb},
+ {0x59, 0x00, 0xff, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x39, 0x03, 0xca, 0xbb},
+ {0x3a, 0x06, 0x80, 0xbb},
+ {0x3b, 0x01, 0x52, 0xbb},
+ {0x3c, 0x05, 0x40, 0xbb},
+ {0x57, 0x01, 0x9c, 0xbb},
+ {0x58, 0x01, 0xee, 0xbb},
+ {0x59, 0x00, 0xf0, 0xbb},
+ {0x5a, 0x01, 0x20, 0xbb},
+ {0x5c, 0x1d, 0x17, 0xbb},
+ {0x5d, 0x22, 0x1c, 0xbb},
+ {0x64, 0x1e, 0x1c, 0xbb},
+ {0x5b, 0x00, 0x00, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x22, 0xa0, 0x78, 0xbb},
+ {0x23, 0xa0, 0x78, 0xbb},
+ {0x24, 0x7f, 0x00, 0xbb},
+ {0x28, 0xea, 0x02, 0xbb},
+ {0x29, 0x86, 0x7a, 0xbb},
+ {0x5e, 0x52, 0x4c, 0xbb},
+ {0x5f, 0x20, 0x24, 0xbb},
+ {0x60, 0x00, 0x02, 0xbb},
+ {0x02, 0x00, 0xee, 0xbb},
+ {0x03, 0x39, 0x23, 0xbb},
+ {0x04, 0x07, 0x24, 0xbb},
+ {0x09, 0x00, 0xc0, 0xbb},
+ {0x0a, 0x00, 0x79, 0xbb},
+ {0x0b, 0x00, 0x04, 0xbb},
+ {0x0c, 0x00, 0x5c, 0xbb},
+ {0x0d, 0x00, 0xd9, 0xbb},
+ {0x0e, 0x00, 0x53, 0xbb},
+ {0x0f, 0x00, 0x21, 0xbb},
+ {0x10, 0x00, 0xa4, 0xbb},
+ {0x11, 0x00, 0xe5, 0xbb},
+ {0x15, 0x00, 0x00, 0xbb},
+ {0x16, 0x00, 0x00, 0xbb},
+ {0x17, 0x00, 0x00, 0xbb},
+ {0x18, 0x00, 0x00, 0xbb},
+ {0x19, 0x00, 0x00, 0xbb},
+ {0x1a, 0x00, 0x00, 0xbb},
+ {0x1b, 0x00, 0x00, 0xbb},
+ {0x1c, 0x00, 0x00, 0xbb},
+ {0x1d, 0x00, 0x00, 0xbb},
+ {0x1e, 0x00, 0x00, 0xbb},
+ {0xf0, 0x00, 0x01, 0xbb},
+ {0x06, 0xe0, 0x0e, 0xbb},
+ {0x06, 0x60, 0x0e, 0xbb},
+ {0xb3, 0x5c, 0x01, 0xcc},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x05, 0x01, 0x13, 0xbb},
+ {0x06, 0x00, 0x11, 0xbb},
+ {0x07, 0x00, 0x85, 0xbb},
+ {0x08, 0x00, 0x27, 0xbb},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0x21, 0x80, 0x00, 0xbb},
+ {0x22, 0x0d, 0x0f, 0xbb},
+ {0x24, 0x80, 0x00, 0xbb},
+ {0x59, 0x00, 0xff, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x39, 0x03, 0x0d, 0xbb},
+ {0x3a, 0x06, 0x1b, 0xbb},
+ {0x3b, 0x00, 0x95, 0xbb},
+ {0x3c, 0x04, 0xdb, 0xbb},
+ {0x57, 0x02, 0x00, 0xbb},
+ {0x58, 0x02, 0x66, 0xbb},
+ {0x59, 0x00, 0xff, 0xbb},
+ {0x5a, 0x01, 0x33, 0xbb},
+ {0x5c, 0x12, 0x0d, 0xbb},
+ {0x5d, 0x16, 0x11, 0xbb},
+ {0x64, 0x5e, 0x1c, 0xbb},
+ {0x2f, 0x90, 0x00, 0xbb},
+ {}
+};
+static const u8 mi1320_soc_InitSXGA[][4] = {
+ {0xb3, 0x01, 0x01, 0xcc},
+ {0xb0, 0x03, 0x19, 0xcc},
+ {0x00, 0x00, 0x30, 0xdd},
+ {0xb3, 0x00, 0x64, 0xcc},
+ {0xb3, 0x00, 0x67, 0xcc},
+ {0xb3, 0x05, 0x01, 0xcc},
+ {0xb3, 0x06, 0x01, 0xcc},
+ {0xb3, 0x08, 0x01, 0xcc},
+ {0xb3, 0x09, 0x0c, 0xcc},
+ {0xb3, 0x34, 0x02, 0xcc},
+ {0xb3, 0x35, 0xc8, 0xcc},
+ {0xb3, 0x02, 0x00, 0xcc},
+ {0xb3, 0x03, 0x0a, 0xcc},
+ {0xb3, 0x04, 0x05, 0xcc},
+ {0xb3, 0x20, 0x00, 0xcc},
+ {0xb3, 0x21, 0x00, 0xcc},
+ {0xb3, 0x22, 0x04, 0xcc},
+ {0xb3, 0x23, 0x00, 0xcc},
+ {0xb3, 0x14, 0x00, 0xcc},
+ {0xb3, 0x15, 0x00, 0xcc},
+ {0xb3, 0x16, 0x04, 0xcc},
+ {0xb3, 0x17, 0xff, 0xcc},
+ {0xb3, 0x00, 0x67, 0xcc},
+ {0xbc, 0x00, 0x71, 0xcc},
+ {0xbc, 0x01, 0x01, 0xcc},
+ {0xb3, 0x5c, 0x01, 0xcc},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x00, 0x00, 0x30, 0xdd},
+ {0xc8, 0x9f, 0x0b, 0xbb},
+ {0x00, 0x00, 0x20, 0xdd},
+ {0x5b, 0x00, 0x01, 0xbb},
+ {0x00, 0x00, 0x20, 0xdd},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x00, 0x00, 0x30, 0xdd},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0x00, 0x00, 0x20, 0xdd},
+ {0xbf, 0xc0, 0x26, 0xcc},
+ {0xbf, 0xc1, 0x02, 0xcc},
+ {0xbf, 0xcc, 0x04, 0xcc},
+ {0xb3, 0x01, 0x41, 0xcc},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x05, 0x01, 0x78, 0xbb},
+ {0x06, 0x00, 0x11, 0xbb},
+ {0x07, 0x01, 0x42, 0xbb},
+ {0x08, 0x00, 0x11, 0xbb},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0x21, 0x80, 0x00, 0xbb},
+ {0x22, 0x0d, 0x0f, 0xbb},
+ {0x24, 0x80, 0x00, 0xbb},
+ {0x59, 0x00, 0xff, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x39, 0x03, 0xca, 0xbb},
+ {0x3a, 0x06, 0x80, 0xbb},
+ {0x3b, 0x01, 0x52, 0xbb},
+ {0x3c, 0x05, 0x40, 0xbb},
+ {0x57, 0x01, 0x9c, 0xbb},
+ {0x58, 0x01, 0xee, 0xbb},
+ {0x59, 0x00, 0xf0, 0xbb},
+ {0x5a, 0x01, 0x20, 0xbb},
+ {0x5c, 0x1d, 0x17, 0xbb},
+ {0x5d, 0x22, 0x1c, 0xbb},
+ {0x64, 0x1e, 0x1c, 0xbb},
+ {0x5b, 0x00, 0x00, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x22, 0xa0, 0x78, 0xbb},
+ {0x23, 0xa0, 0x78, 0xbb},
+ {0x24, 0x7f, 0x00, 0xbb},
+ {0x28, 0xea, 0x02, 0xbb},
+ {0x29, 0x86, 0x7a, 0xbb},
+ {0x5e, 0x52, 0x4c, 0xbb},
+ {0x5f, 0x20, 0x24, 0xbb},
+ {0x60, 0x00, 0x02, 0xbb},
+ {0x02, 0x00, 0xee, 0xbb},
+ {0x03, 0x39, 0x23, 0xbb},
+ {0x04, 0x07, 0x24, 0xbb},
+ {0x09, 0x00, 0xc0, 0xbb},
+ {0x0a, 0x00, 0x79, 0xbb},
+ {0x0b, 0x00, 0x04, 0xbb},
+ {0x0c, 0x00, 0x5c, 0xbb},
+ {0x0d, 0x00, 0xd9, 0xbb},
+ {0x0e, 0x00, 0x53, 0xbb},
+ {0x0f, 0x00, 0x21, 0xbb},
+ {0x10, 0x00, 0xa4, 0xbb},
+ {0x11, 0x00, 0xe5, 0xbb},
+ {0x15, 0x00, 0x00, 0xbb},
+ {0x16, 0x00, 0x00, 0xbb},
+ {0x17, 0x00, 0x00, 0xbb},
+ {0x18, 0x00, 0x00, 0xbb},
+ {0x19, 0x00, 0x00, 0xbb},
+ {0x1a, 0x00, 0x00, 0xbb},
+ {0x1b, 0x00, 0x00, 0xbb},
+ {0x1c, 0x00, 0x00, 0xbb},
+ {0x1d, 0x00, 0x00, 0xbb},
+ {0x1e, 0x00, 0x00, 0xbb},
+ {0xf0, 0x00, 0x01, 0xbb},
+ {0x06, 0xe0, 0x0e, 0xbb},
+ {0x06, 0x60, 0x0e, 0xbb},
+ {0xb3, 0x5c, 0x01, 0xcc},
+ {0xf0, 0x00, 0x00, 0xbb},
+ {0x05, 0x01, 0x13, 0xbb},
+ {0x06, 0x00, 0x11, 0xbb},
+ {0x07, 0x00, 0x85, 0xbb},
+ {0x08, 0x00, 0x27, 0xbb},
+ {0x20, 0x01, 0x03, 0xbb},
+ {0x21, 0x80, 0x00, 0xbb},
+ {0x22, 0x0d, 0x0f, 0xbb},
+ {0x24, 0x80, 0x00, 0xbb},
+ {0x59, 0x00, 0xff, 0xbb},
+ {0xf0, 0x00, 0x02, 0xbb},
+ {0x39, 0x03, 0x0d, 0xbb},
+ {0x3a, 0x06, 0x1b, 0xbb},
+ {0x3b, 0x00, 0x95, 0xbb},
+ {0x3c, 0x04, 0xdb, 0xbb},
+ {0x57, 0x02, 0x00, 0xbb},
+ {0x58, 0x02, 0x66, 0xbb},
+ {0x59, 0x00, 0xff, 0xbb},
+ {0x5a, 0x01, 0x33, 0xbb},
+ {0x5c, 0x12, 0x0d, 0xbb},
+ {0x5d, 0x16, 0x11, 0xbb},
+ {0x64, 0x5e, 0x1c, 0xbb},
+ {}
+};
static const __u8 po3130_gamma[17] = {
0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
@@ -1936,9 +2692,10 @@ static const struct sensor_info sensor_info_data[] = {
{-1, 0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01},
{-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
{-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01},
- {-1, 0x80 | 0x48, 0x00, 0x0000, 0x64, 0x67, 0x01},
-/*fixme: not in the ms-win probe - may be found before?*/
+ {SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01},
+/*fixme: previously detected?*/
{SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01},
+/*fixme: not in the ms-win probe - may be found before?*/
{SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05},
#else
{SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
@@ -2059,33 +2816,19 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev)
}
static void i2c_write(struct gspca_dev *gspca_dev,
- __u8 reg, const __u8 *val, __u8 size)
+ u8 reg, const u8 *val,
+ u8 size) /* 1 or 2 */
{
struct usb_device *dev = gspca_dev->dev;
int retry;
-#ifdef GSPCA_DEBUG
- if (size > 3 || size < 1)
- return;
-#endif
reg_r(gspca_dev, 0xa1, 0xb33f, 1);
+/*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/
reg_w(dev, 0xa0, size, 0xb334);
reg_w(dev, 0xa0, reg, 0xb33a);
- switch (size) {
- case 1:
- reg_w(dev, 0xa0, val[0], 0xb336);
- break;
- case 2:
- reg_w(dev, 0xa0, val[0], 0xb336);
+ reg_w(dev, 0xa0, val[0], 0xb336);
+ if (size > 1)
reg_w(dev, 0xa0, val[1], 0xb337);
- break;
- default:
-/* case 3: */
- reg_w(dev, 0xa0, val[0], 0xb336);
- reg_w(dev, 0xa0, val[1], 0xb337);
- reg_w(dev, 0xa0, val[2], 0xb338);
- break;
- }
reg_w(dev, 0xa0, 0x01, 0xb339);
retry = 4;
do {
@@ -2180,6 +2923,9 @@ static int sd_config(struct gspca_dev *gspca_dev,
case SENSOR_MI1320:
PDEBUG(D_PROBE, "Find Sensor MI1320");
break;
+ case SENSOR_MI1320_SOC:
+ PDEBUG(D_PROBE, "Find Sensor MI1320_SOC");
+ break;
case SENSOR_OV7660:
PDEBUG(D_PROBE, "Find Sensor OV7660");
break;
@@ -2199,15 +2945,23 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->cam_mode = vc0321_mode;
cam->nmodes = ARRAY_SIZE(vc0321_mode);
} else {
- if (sensor != SENSOR_PO1200) {
- cam->cam_mode = vc0323_mode;
- if (sd->sensor != SENSOR_MI1310_SOC)
- cam->nmodes = ARRAY_SIZE(vc0323_mode);
- else /* no SXGA */
- cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1;
- } else {
+ switch (sensor) {
+ case SENSOR_PO1200:
cam->cam_mode = svga_mode;
cam->nmodes = ARRAY_SIZE(svga_mode);
+ break;
+ case SENSOR_MI1310_SOC:
+ cam->cam_mode = vc0323_mode;
+ cam->nmodes = ARRAY_SIZE(vc0323_mode);
+ break;
+ case SENSOR_MI1320_SOC:
+ cam->cam_mode = bi_mode;
+ cam->nmodes = ARRAY_SIZE(bi_mode);
+ break;
+ default:
+ cam->cam_mode = vc0323_mode;
+ cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1;
+ break;
}
}
@@ -2310,6 +3064,14 @@ static int sd_start(struct gspca_dev *gspca_dev)
const __u8 *GammaT = NULL;
const __u8 *MatrixT = NULL;
int mode;
+ static const u8 (*mi1320_soc_init[])[4] = {
+ mi1320_soc_InitSXGA,
+ mi1320_soc_InitSXGA_JPG,
+ mi1320_soc_InitVGA,
+ mi1320_soc_InitVGA_JPG,
+ mi1320_soc_InitQVGA,
+ mi1320_soc_InitQVGA_JPG
+ };
/* Assume start use the good resolution from gspca_dev->mode */
if (sd->bridge == BRIDGE_VC0321) {
@@ -2317,6 +3079,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfed);
reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfee);
reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfef);
+ sd->image_offset = 46;
+ } else {
+ if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].pixelformat
+ == V4L2_PIX_FMT_JPEG)
+ sd->image_offset = 0;
+ else
+ sd->image_offset = 32;
}
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
@@ -2364,7 +3133,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
init = mi1310_socinitVGA_JPG; /* 640x480 */
break;
default:
- init = mi1310_soc_InitSXGA_JPG; /* 1280xq024 */
+ init = mi1310_soc_InitSXGA_JPG; /* 1280x1024 */
break;
}
break;
@@ -2376,6 +3145,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
else
init = mi1320_initVGA_data; /* 640x480 */
break;
+ case SENSOR_MI1320_SOC:
+ GammaT = mi1320_gamma;
+ MatrixT = mi1320_matrix;
+ init = mi1320_soc_init[mode];
+ break;
case SENSOR_PO3130NC:
GammaT = po3130_gamma;
MatrixT = po3130_matrix;
@@ -2446,12 +3220,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
"vc032x header packet found len %d", len);
frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
data, 0);
- if (sd->bridge == BRIDGE_VC0321) {
-#define VCHDRSZ 46
- data += VCHDRSZ;
- len -= VCHDRSZ;
-#undef VCHDRSZ
- }
+ data += sd->image_offset;
+ len -= sd->image_offset;
gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
data, len);
return;
@@ -2584,6 +3354,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0ac8, 0x0328), .driver_info = BRIDGE_VC0321},
{USB_DEVICE(0x0ac8, 0xc001), .driver_info = BRIDGE_VC0321},
{USB_DEVICE(0x0ac8, 0xc002), .driver_info = BRIDGE_VC0321},
+ {USB_DEVICE(0x15b8, 0x6001), .driver_info = BRIDGE_VC0323},
{USB_DEVICE(0x15b8, 0x6002), .driver_info = BRIDGE_VC0323},
{USB_DEVICE(0x17ef, 0x4802), .driver_info = BRIDGE_VC0323},
{}
diff --git a/linux/drivers/media/video/pvrusb2/Makefile b/linux/drivers/media/video/pvrusb2/Makefile
index 4fda2de69..a4478618a 100644
--- a/linux/drivers/media/video/pvrusb2/Makefile
+++ b/linux/drivers/media/video/pvrusb2/Makefile
@@ -2,10 +2,10 @@ obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o
-pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
- pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
+pvrusb2-objs := pvrusb2-i2c-core.o \
+ pvrusb2-audio.o \
pvrusb2-encoder.o pvrusb2-video-v4l.o \
- pvrusb2-eeprom.o pvrusb2-tuner.o \
+ pvrusb2-eeprom.o \
pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \
pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \
pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c
index 65babb878..61cc80ef2 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c
@@ -27,14 +27,6 @@
#include <media/v4l2-common.h>
#include "compat.h"
-struct pvr2_msp3400_handler {
- struct pvr2_hdw *hdw;
- struct pvr2_i2c_client *client;
- struct pvr2_i2c_handler i2c_handler;
- unsigned long stale_mask;
-};
-
-
struct routing_scheme {
const int *def;
@@ -64,123 +56,33 @@ static const struct routing_scheme routing_schemes[] = {
},
};
-/* This function selects the correct audio input source */
-static void set_stereo(struct pvr2_msp3400_handler *ctxt)
-{
- struct pvr2_hdw *hdw = ctxt->hdw;
- struct v4l2_routing route;
- const struct routing_scheme *sp;
- unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
-
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo");
-
- if ((sid < ARRAY_SIZE(routing_schemes)) &&
- ((sp = routing_schemes + sid) != NULL) &&
- (hdw->input_val >= 0) &&
- (hdw->input_val < sp->cnt)) {
- route.input = sp->def[hdw->input_val];
- } else {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "*** WARNING *** i2c msp3400 v4l2 set_stereo:"
- " Invalid routing scheme (%u) and/or input (%d)",
- sid,hdw->input_val);
- return;
- }
- route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
- pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
-}
-
-
-static int check_stereo(struct pvr2_msp3400_handler *ctxt)
+void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
{
- struct pvr2_hdw *hdw = ctxt->hdw;
- return hdw->input_dirty;
-}
-
-
-struct pvr2_msp3400_ops {
- void (*update)(struct pvr2_msp3400_handler *);
- int (*check)(struct pvr2_msp3400_handler *);
-};
-
-
-static const struct pvr2_msp3400_ops msp3400_ops[] = {
- { .update = set_stereo, .check = check_stereo},
-};
-
-
-static int msp3400_check(struct pvr2_msp3400_handler *ctxt)
-{
- unsigned long msk;
- unsigned int idx;
-
- for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) {
- msk = 1 << idx;
- if (ctxt->stale_mask & msk) continue;
- if (msp3400_ops[idx].check(ctxt)) {
- ctxt->stale_mask |= msk;
+ if (hdw->input_dirty || hdw->force_dirty) {
+ struct v4l2_routing route;
+ const struct routing_scheme *sp;
+ unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
+
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo");
+
+ if ((sid < ARRAY_SIZE(routing_schemes)) &&
+ ((sp = routing_schemes + sid) != NULL) &&
+ (hdw->input_val >= 0) &&
+ (hdw->input_val < sp->cnt)) {
+ route.input = sp->def[hdw->input_val];
+ } else {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "*** WARNING *** subdev msp3400 set_input:"
+ " Invalid routing scheme (%u)"
+ " and/or input (%d)",
+ sid, hdw->input_val);
+ return;
}
+ route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
+ sd->ops->audio->s_routing(sd, &route);
}
- return ctxt->stale_mask != 0;
}
-
-static void msp3400_update(struct pvr2_msp3400_handler *ctxt)
-{
- unsigned long msk;
- unsigned int idx;
-
- for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) {
- msk = 1 << idx;
- if (!(ctxt->stale_mask & msk)) continue;
- ctxt->stale_mask &= ~msk;
- msp3400_ops[idx].update(ctxt);
- }
-}
-
-
-static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt)
-{
- ctxt->client->handler = NULL;
- kfree(ctxt);
-}
-
-
-static unsigned int pvr2_msp3400_describe(struct pvr2_msp3400_handler *ctxt,
- char *buf,unsigned int cnt)
-{
- return scnprintf(buf,cnt,"handler: pvrusb2-audio v4l2");
-}
-
-
-static const struct pvr2_i2c_handler_functions msp3400_funcs = {
- .detach = (void (*)(void *))pvr2_msp3400_detach,
- .check = (int (*)(void *))msp3400_check,
- .update = (void (*)(void *))msp3400_update,
- .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_msp3400_describe,
-};
-
-
-int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
-{
- struct pvr2_msp3400_handler *ctxt;
- if (cp->handler) return 0;
-
- ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
- if (!ctxt) return 0;
-
- ctxt->i2c_handler.func_data = ctxt;
- ctxt->i2c_handler.func_table = &msp3400_funcs;
- ctxt->client = cp;
- ctxt->hdw = hdw;
- ctxt->stale_mask = (1 << ARRAY_SIZE(msp3400_ops)) - 1;
- cp->handler = &ctxt->i2c_handler;
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up",
- cp->client->addr);
- return !0;
-}
-
-
/*
Stuff for Emacs to see, in order to encourage consistent editing style:
*** Local Variables: ***
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h
index ac54eed37..e3e63d750 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h
@@ -22,10 +22,8 @@
#ifndef __PVRUSB2_AUDIO_H
#define __PVRUSB2_AUDIO_H
-#include "pvrusb2-i2c-core.h"
-
-int pvr2_i2c_msp3400_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
-
+#include "pvrusb2-hdw-internal.h"
+void pvr2_msp3400_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *);
#endif /* __PVRUSB2_AUDIO_H */
/*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c
new file mode 100644
index 000000000..932943bd7
--- /dev/null
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c
@@ -0,0 +1,96 @@
+/*
+ *
+ *
+ * Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ * 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
+ *
+ * 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 source file is specifically designed to interface with the
+ v4l-dvb cs53l32a module.
+
+*/
+
+#include "pvrusb2-cs53l32a.h"
+
+
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include "compat.h"
+
+struct routing_scheme {
+ const int *def;
+ unsigned int cnt;
+};
+
+
+static const int routing_scheme1[] = {
+ [PVR2_CVAL_INPUT_TV] = 2, /* 1 or 2 seems to work here */
+ [PVR2_CVAL_INPUT_RADIO] = 2,
+ [PVR2_CVAL_INPUT_COMPOSITE] = 0,
+ [PVR2_CVAL_INPUT_SVIDEO] = 0,
+};
+
+static const struct routing_scheme routing_schemes[] = {
+ [PVR2_ROUTING_SCHEME_ONAIR] = {
+ .def = routing_scheme1,
+ .cnt = ARRAY_SIZE(routing_scheme1),
+ },
+};
+
+
+void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
+{
+ if (hdw->input_dirty || hdw->force_dirty) {
+ struct v4l2_routing route;
+ const struct routing_scheme *sp;
+ unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)",
+ hdw->input_val);
+ if ((sid < ARRAY_SIZE(routing_schemes)) &&
+ ((sp = routing_schemes + sid) != NULL) &&
+ (hdw->input_val >= 0) &&
+ (hdw->input_val < sp->cnt)) {
+ route.input = sp->def[hdw->input_val];
+ } else {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "*** WARNING *** subdev v4l2 set_input:"
+ " Invalid routing scheme (%u)"
+ " and/or input (%d)",
+ sid, hdw->input_val);
+ return;
+ }
+ route.output = 0;
+ sd->ops->audio->s_routing(sd, &route);
+ }
+}
+
+
+/*
+ Stuff for Emacs to see, in order to encourage consistent editing style:
+ *** Local Variables: ***
+ *** mode: c ***
+ *** fill-column: 70 ***
+ *** tab-width: 8 ***
+ *** c-basic-offset: 8 ***
+ *** End: ***
+ */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h
index ef4afaf37..53ba548b7 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h
@@ -2,6 +2,7 @@
*
*
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
*
* 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
@@ -17,14 +18,24 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
-#ifndef __PVRUSB2_TUNER_H
-#define __PVRUSB2_TUNER_H
-#include "pvrusb2-i2c-core.h"
+#ifndef __PVRUSB2_CS53L32A_H
+#define __PVRUSB2_CS53L32A_H
-int pvr2_i2c_tuner_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+/*
+
+ This module connects the pvrusb2 driver to the I2C chip level
+ driver which handles device video processing. This interface is
+ used internally by the driver; higher level code should only
+ interact through the interface provided by pvrusb2-hdw.h.
+
+*/
+
+
+#include "pvrusb2-hdw-internal.h"
+void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *);
-#endif /* __PVRUSB2_TUNER_H */
+#endif /* __PVRUSB2_AUDIO_CS53L32A_H */
/*
Stuff for Emacs to see, in order to encourage consistent editing style:
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
index 2f051f797..e0a6de5ae 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
@@ -28,7 +28,6 @@
#include "pvrusb2-cx2584x-v4l.h"
#include "pvrusb2-video-v4l.h"
-#include "pvrusb2-i2c-cmd-v4l2.h"
#include "pvrusb2-hdw-internal.h"
@@ -40,14 +39,6 @@
#include <linux/slab.h>
#include "compat.h"
-struct pvr2_v4l_cx2584x {
- struct pvr2_i2c_handler handler;
- struct pvr2_decoder_ctrl ctrl;
- struct pvr2_i2c_client *client;
- struct pvr2_hdw *hdw;
- unsigned long stale_mask;
-};
-
struct routing_scheme_item {
int vid;
@@ -111,218 +102,44 @@ static const struct routing_scheme routing_schemes[] = {
},
};
-static void set_input(struct pvr2_v4l_cx2584x *ctxt)
-{
- struct pvr2_hdw *hdw = ctxt->hdw;
- struct v4l2_routing route;
- enum cx25840_video_input vid_input;
- enum cx25840_audio_input aud_input;
- const struct routing_scheme *sp;
- unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
-
- memset(&route,0,sizeof(route));
-
- if ((sid < ARRAY_SIZE(routing_schemes)) &&
- ((sp = routing_schemes + sid) != NULL) &&
- (hdw->input_val >= 0) &&
- (hdw->input_val < sp->cnt)) {
- vid_input = sp->def[hdw->input_val].vid;
- aud_input = sp->def[hdw->input_val].aud;
- } else {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "*** WARNING *** i2c cx2584x set_input:"
- " Invalid routing scheme (%u) and/or input (%d)",
- sid,hdw->input_val);
- return;
- }
-
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_input vid=0x%x aud=0x%x",
- vid_input,aud_input);
- route.input = (u32)vid_input;
- pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route);
- route.input = (u32)aud_input;
- pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
-}
-
-
-static int check_input(struct pvr2_v4l_cx2584x *ctxt)
-{
- struct pvr2_hdw *hdw = ctxt->hdw;
- return hdw->input_dirty != 0;
-}
-
-
-static void set_audio(struct pvr2_v4l_cx2584x *ctxt)
-{
- u32 val;
- struct pvr2_hdw *hdw = ctxt->hdw;
-
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_audio %d",
- hdw->srate_val);
- switch (hdw->srate_val) {
- default:
- case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
- val = 48000;
- break;
- case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
- val = 44100;
- break;
- case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
- val = 32000;
- break;
- }
- pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val);
-}
-
-
-static int check_audio(struct pvr2_v4l_cx2584x *ctxt)
-{
- struct pvr2_hdw *hdw = ctxt->hdw;
- return hdw->srate_dirty != 0;
-}
-
-
-struct pvr2_v4l_cx2584x_ops {
- void (*update)(struct pvr2_v4l_cx2584x *);
- int (*check)(struct pvr2_v4l_cx2584x *);
-};
-
-
-static const struct pvr2_v4l_cx2584x_ops decoder_ops[] = {
- { .update = set_input, .check = check_input},
- { .update = set_audio, .check = check_audio},
-};
-
-
-static void decoder_detach(struct pvr2_v4l_cx2584x *ctxt)
+void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
{
- ctxt->client->handler = NULL;
- pvr2_hdw_set_decoder(ctxt->hdw,NULL);
- kfree(ctxt);
-}
-
-
-static int decoder_check(struct pvr2_v4l_cx2584x *ctxt)
-{
- unsigned long msk;
- unsigned int idx;
-
- for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
- msk = 1 << idx;
- if (ctxt->stale_mask & msk) continue;
- if (decoder_ops[idx].check(ctxt)) {
- ctxt->stale_mask |= msk;
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update...");
+ if (hdw->input_dirty || hdw->force_dirty) {
+ struct v4l2_routing route;
+ enum cx25840_video_input vid_input;
+ enum cx25840_audio_input aud_input;
+ const struct routing_scheme *sp;
+ unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
+
+ memset(&route, 0, sizeof(route));
+
+ if ((sid < ARRAY_SIZE(routing_schemes)) &&
+ ((sp = routing_schemes + sid) != NULL) &&
+ (hdw->input_val >= 0) &&
+ (hdw->input_val < sp->cnt)) {
+ vid_input = sp->def[hdw->input_val].vid;
+ aud_input = sp->def[hdw->input_val].aud;
+ } else {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "*** WARNING *** subdev cx2584x set_input:"
+ " Invalid routing scheme (%u)"
+ " and/or input (%d)",
+ sid, hdw->input_val);
+ return;
}
- }
- return ctxt->stale_mask != 0;
-}
-
-static void decoder_update(struct pvr2_v4l_cx2584x *ctxt)
-{
- unsigned long msk;
- unsigned int idx;
-
- for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
- msk = 1 << idx;
- if (!(ctxt->stale_mask & msk)) continue;
- ctxt->stale_mask &= ~msk;
- decoder_ops[idx].update(ctxt);
+ pvr2_trace(PVR2_TRACE_CHIPS,
+ "subdev cx2584x set_input vid=0x%x aud=0x%x",
+ vid_input, aud_input);
+ route.input = (u32)vid_input;
+ sd->ops->video->s_routing(sd, &route);
+ route.input = (u32)aud_input;
+ sd->ops->audio->s_routing(sd, &route);
}
}
-static void decoder_enable(struct pvr2_v4l_cx2584x *ctxt,int fl)
-{
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_enable(%d)",fl);
- pvr2_v4l2_cmd_stream(ctxt->client,fl);
-}
-
-
-static int decoder_detect(struct pvr2_i2c_client *cp)
-{
- int ret;
- /* Attempt to query the decoder - let's see if it will answer */
- struct v4l2_queryctrl qc;
-
- memset(&qc,0,sizeof(qc));
-
- qc.id = V4L2_CID_BRIGHTNESS;
-
- ret = pvr2_i2c_client_cmd(cp,VIDIOC_QUERYCTRL,&qc);
- return ret == 0; /* Return true if it answered */
-}
-
-
-static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt,
- char *buf,unsigned int cnt)
-{
- return scnprintf(buf,cnt,"handler: pvrusb2-cx2584x-v4l");
-}
-
-
-static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt)
-{
- int ret;
- ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,NULL);
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_reset (ret=%d)",ret);
-}
-
-
-static const struct pvr2_i2c_handler_functions hfuncs = {
- .detach = (void (*)(void *))decoder_detach,
- .check = (int (*)(void *))decoder_check,
- .update = (void (*)(void *))decoder_update,
- .describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe,
-};
-
-
-int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw,
- struct pvr2_i2c_client *cp)
-{
- struct pvr2_v4l_cx2584x *ctxt;
-
- if (hdw->decoder_ctrl) return 0;
- if (cp->handler) return 0;
- if (!decoder_detect(cp)) return 0;
-
- ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
- if (!ctxt) return 0;
-
- ctxt->handler.func_data = ctxt;
- ctxt->handler.func_table = &hfuncs;
- ctxt->ctrl.ctxt = ctxt;
- ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
- ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
- ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset;
- ctxt->client = cp;
- ctxt->hdw = hdw;
- ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1;
- pvr2_hdw_set_decoder(hdw,&ctxt->ctrl);
- cp->handler = &ctxt->handler;
- {
- /*
- Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit
- of nuttiness for cx25840 causes that module to
- correctly set up its video scaling. This is really
- a problem in the cx25840 module itself, but we work
- around it here. The problem has not been seen in
- ivtv because there VBI is supported and set up. We
- don't do VBI here (at least not yet) and thus we
- never attempted to even set it up.
- */
- struct v4l2_format fmt;
- memset(&fmt,0,sizeof(fmt));
- fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
- pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt);
- }
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up",
- cp->client->addr);
- return !0;
-}
-
-
-
/*
Stuff for Emacs to see, in order to encourage consistent editing style:
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
index 66abf77f5..e35c2322a 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
@@ -34,9 +34,9 @@
-#include "pvrusb2-i2c-core.h"
+#include "pvrusb2-hdw-internal.h"
-int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+void pvr2_cx25840_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd);
#endif /* __PVRUSB2_CX2584X_V4L_H */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
index ca892fb78..fbe3856bd 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
@@ -23,7 +23,6 @@
#include "pvrusb2-debugifc.h"
#include "pvrusb2-hdw.h"
#include "pvrusb2-debug.h"
-#include "pvrusb2-i2c-core.h"
struct debugifc_mask_item {
const char *name;
@@ -147,10 +146,6 @@ int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt)
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
ccnt = pvr2_hdw_state_report(hdw,buf,acnt);
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
- ccnt = scnprintf(buf,acnt,"Attached I2C modules:\n");
- bcnt += ccnt; acnt -= ccnt; buf += ccnt;
- ccnt = pvr2_i2c_report(hdw,buf,acnt);
- bcnt += ccnt; acnt -= ccnt; buf += ccnt;
return bcnt;
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
index e24ff59f8..2f8d46761 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
@@ -22,16 +22,16 @@
struct pvr2_hdw;
-/* Non-intrusively print some useful debugging info from inside the
- driver. This should work even if the driver appears to be
- wedged. */
-int pvr2_debugifc_print_info(struct pvr2_hdw *,
- char *buf_ptr,unsigned int buf_size);
-
/* Print general status of driver. This will also trigger a probe of
the USB link. Unlike print_info(), this one synchronizes with the
driver so the information should be self-consistent (but it will
hang if the driver is wedged). */
+int pvr2_debugifc_print_info(struct pvr2_hdw *,
+ char *buf_ptr, unsigned int buf_size);
+
+/* Non-intrusively print some useful debugging info from inside the
+ driver. This should work even if the driver appears to be
+ wedged. */
int pvr2_debugifc_print_status(struct pvr2_hdw *,
char *buf_ptr,unsigned int buf_size);
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c
index cbe2a3417..1cb6a260e 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c
@@ -46,10 +46,11 @@ pvr2_device_desc structures.
/*------------------------------------------------------------------------*/
/* Hauppauge PVR-USB2 Model 29xxx */
-static const char *pvr2_client_29xxx[] = {
- "msp3400",
- "saa7115",
- "tuner",
+static const struct pvr2_device_client_desc pvr2_cli_29xxx[] = {
+ { .module_id = PVR2_CLIENT_ID_SAA7115 },
+ { .module_id = PVR2_CLIENT_ID_MSP3400 },
+ { .module_id = PVR2_CLIENT_ID_TUNER },
+ { .module_id = PVR2_CLIENT_ID_DEMOD },
};
static const char *pvr2_fw1_names_29xxx[] = {
@@ -59,8 +60,8 @@ static const char *pvr2_fw1_names_29xxx[] = {
static const struct pvr2_device_desc pvr2_device_29xxx = {
.description = "WinTV PVR USB2 Model Category 29xxx",
.shortname = "29xxx",
- .client_modules.lst = pvr2_client_29xxx,
- .client_modules.cnt = ARRAY_SIZE(pvr2_client_29xxx),
+ .client_table.lst = pvr2_cli_29xxx,
+ .client_table.cnt = ARRAY_SIZE(pvr2_cli_29xxx),
.fx2_firmware.lst = pvr2_fw1_names_29xxx,
.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx),
.flag_has_hauppauge_rom = !0,
@@ -77,10 +78,11 @@ static const struct pvr2_device_desc pvr2_device_29xxx = {
/*------------------------------------------------------------------------*/
/* Hauppauge PVR-USB2 Model 24xxx */
-static const char *pvr2_client_24xxx[] = {
- "cx25840",
- "tuner",
- "wm8775",
+static const struct pvr2_device_client_desc pvr2_cli_24xxx[] = {
+ { .module_id = PVR2_CLIENT_ID_CX25840 },
+ { .module_id = PVR2_CLIENT_ID_TUNER },
+ { .module_id = PVR2_CLIENT_ID_WM8775 },
+ { .module_id = PVR2_CLIENT_ID_DEMOD },
};
static const char *pvr2_fw1_names_24xxx[] = {
@@ -90,8 +92,8 @@ static const char *pvr2_fw1_names_24xxx[] = {
static const struct pvr2_device_desc pvr2_device_24xxx = {
.description = "WinTV PVR USB2 Model Category 24xxx",
.shortname = "24xxx",
- .client_modules.lst = pvr2_client_24xxx,
- .client_modules.cnt = ARRAY_SIZE(pvr2_client_24xxx),
+ .client_table.lst = pvr2_cli_24xxx,
+ .client_table.cnt = ARRAY_SIZE(pvr2_cli_24xxx),
.fx2_firmware.lst = pvr2_fw1_names_24xxx,
.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_24xxx),
.flag_has_cx25840 = !0,
@@ -111,16 +113,16 @@ static const struct pvr2_device_desc pvr2_device_24xxx = {
/*------------------------------------------------------------------------*/
/* GOTVIEW USB2.0 DVD2 */
-static const char *pvr2_client_gotview_2[] = {
- "cx25840",
- "tuner",
+static const struct pvr2_device_client_desc pvr2_cli_gotview_2[] = {
+ { .module_id = PVR2_CLIENT_ID_CX25840 },
+ { .module_id = PVR2_CLIENT_ID_TUNER },
};
static const struct pvr2_device_desc pvr2_device_gotview_2 = {
.description = "Gotview USB 2.0 DVD 2",
.shortname = "gv2",
- .client_modules.lst = pvr2_client_gotview_2,
- .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2),
+ .client_table.lst = pvr2_cli_gotview_2,
+ .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2),
.flag_has_cx25840 = !0,
.default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
.flag_has_analogtuner = !0,
@@ -140,8 +142,8 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = {
static const struct pvr2_device_desc pvr2_device_gotview_2d = {
.description = "Gotview USB 2.0 DVD Deluxe",
.shortname = "gv2d",
- .client_modules.lst = pvr2_client_gotview_2,
- .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2),
+ .client_table.lst = pvr2_cli_gotview_2,
+ .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2),
.flag_has_cx25840 = !0,
.default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
.flag_has_analogtuner = !0,
@@ -181,29 +183,29 @@ static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap)
return 0;
}
-static struct pvr2_dvb_props pvr2_onair_creator_fe_props = {
+static const struct pvr2_dvb_props pvr2_onair_creator_fe_props = {
.frontend_attach = pvr2_lgdt3303_attach,
.tuner_attach = pvr2_lgh06xf_attach,
};
#endif
-static const char *pvr2_client_onair_creator[] = {
- "saa7115",
- "tuner",
- "cs53l32a",
+static const struct pvr2_device_client_desc pvr2_cli_onair_creator[] = {
+ { .module_id = PVR2_CLIENT_ID_SAA7115 },
+ { .module_id = PVR2_CLIENT_ID_CS53L32A },
+ { .module_id = PVR2_CLIENT_ID_TUNER },
};
static const struct pvr2_device_desc pvr2_device_onair_creator = {
.description = "OnAir Creator Hybrid USB tuner",
.shortname = "oac",
- .client_modules.lst = pvr2_client_onair_creator,
- .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_creator),
+ .client_table.lst = pvr2_cli_onair_creator,
+ .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_creator),
.default_tuner_type = TUNER_LG_TDVS_H06XF,
.flag_has_analogtuner = !0,
.flag_has_composite = !0,
.flag_has_svideo = !0,
.flag_digital_requires_cx23416 = !0,
- .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+ .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR,
.digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
.default_std_mask = V4L2_STD_NTSC_M,
#ifdef CONFIG_VIDEO_PVRUSB2_DVB
@@ -241,29 +243,29 @@ static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap)
return 0;
}
-static struct pvr2_dvb_props pvr2_onair_usb2_fe_props = {
+static const struct pvr2_dvb_props pvr2_onair_usb2_fe_props = {
.frontend_attach = pvr2_lgdt3302_attach,
.tuner_attach = pvr2_fcv1236d_attach,
};
#endif
-static const char *pvr2_client_onair_usb2[] = {
- "saa7115",
- "tuner",
- "cs53l32a",
+static const struct pvr2_device_client_desc pvr2_cli_onair_usb2[] = {
+ { .module_id = PVR2_CLIENT_ID_SAA7115 },
+ { .module_id = PVR2_CLIENT_ID_CS53L32A },
+ { .module_id = PVR2_CLIENT_ID_TUNER },
};
static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
.description = "OnAir USB2 Hybrid USB tuner",
.shortname = "oa2",
- .client_modules.lst = pvr2_client_onair_usb2,
- .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2),
+ .client_table.lst = pvr2_cli_onair_usb2,
+ .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_usb2),
.default_tuner_type = TUNER_PHILIPS_FCV1236D,
.flag_has_analogtuner = !0,
.flag_has_composite = !0,
.flag_has_svideo = !0,
.flag_digital_requires_cx23416 = !0,
- .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+ .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR,
.digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
.default_std_mask = V4L2_STD_NTSC_M,
#ifdef CONFIG_VIDEO_PVRUSB2_DVB
@@ -314,15 +316,16 @@ static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
return 0;
}
-static struct pvr2_dvb_props pvr2_73xxx_dvb_props = {
+static const struct pvr2_dvb_props pvr2_73xxx_dvb_props = {
.frontend_attach = pvr2_tda10048_attach,
.tuner_attach = pvr2_73xxx_tda18271_8295_attach,
};
#endif
-static const char *pvr2_client_73xxx[] = {
- "cx25840",
- "tuner",
+static const struct pvr2_device_client_desc pvr2_cli_73xxx[] = {
+ { .module_id = PVR2_CLIENT_ID_CX25840 },
+ { .module_id = PVR2_CLIENT_ID_TUNER,
+ .i2c_address_list = "\x42"},
};
static const char *pvr2_fw1_names_73xxx[] = {
@@ -332,8 +335,8 @@ static const char *pvr2_fw1_names_73xxx[] = {
static const struct pvr2_device_desc pvr2_device_73xxx = {
.description = "WinTV HVR-1900 Model Category 73xxx",
.shortname = "73xxx",
- .client_modules.lst = pvr2_client_73xxx,
- .client_modules.cnt = ARRAY_SIZE(pvr2_client_73xxx),
+ .client_table.lst = pvr2_cli_73xxx,
+ .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx),
.fx2_firmware.lst = pvr2_fw1_names_73xxx,
.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx),
.flag_has_cx25840 = !0,
@@ -418,22 +421,17 @@ static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
return 0;
}
-static struct pvr2_dvb_props pvr2_750xx_dvb_props = {
+static const struct pvr2_dvb_props pvr2_750xx_dvb_props = {
.frontend_attach = pvr2_s5h1409_attach,
.tuner_attach = pvr2_tda18271_8295_attach,
};
-static struct pvr2_dvb_props pvr2_751xx_dvb_props = {
+static const struct pvr2_dvb_props pvr2_751xx_dvb_props = {
.frontend_attach = pvr2_s5h1411_attach,
.tuner_attach = pvr2_tda18271_8295_attach,
};
#endif
-static const char *pvr2_client_75xxx[] = {
- "cx25840",
- "tuner",
-};
-
static const char *pvr2_fw1_names_75xxx[] = {
"v4l-pvrusb2-73xxx-01.fw",
};
@@ -441,8 +439,8 @@ static const char *pvr2_fw1_names_75xxx[] = {
static const struct pvr2_device_desc pvr2_device_750xx = {
.description = "WinTV HVR-1950 Model Category 750xx",
.shortname = "750xx",
- .client_modules.lst = pvr2_client_75xxx,
- .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
+ .client_table.lst = pvr2_cli_73xxx,
+ .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx),
.fx2_firmware.lst = pvr2_fw1_names_75xxx,
.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
.flag_has_cx25840 = !0,
@@ -463,8 +461,8 @@ static const struct pvr2_device_desc pvr2_device_750xx = {
static const struct pvr2_device_desc pvr2_device_751xx = {
.description = "WinTV HVR-1950 Model Category 751xx",
.shortname = "751xx",
- .client_modules.lst = pvr2_client_75xxx,
- .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
+ .client_table.lst = pvr2_cli_73xxx,
+ .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx),
.fx2_firmware.lst = pvr2_fw1_names_75xxx,
.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
.flag_has_cx25840 = !0,
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h
index cb3a33eb0..3e553389c 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h
@@ -33,6 +33,34 @@
*/
+#define PVR2_CLIENT_ID_NULL 0
+#define PVR2_CLIENT_ID_MSP3400 1
+#define PVR2_CLIENT_ID_CX25840 2
+#define PVR2_CLIENT_ID_SAA7115 3
+#define PVR2_CLIENT_ID_TUNER 4
+#define PVR2_CLIENT_ID_CS53L32A 5
+#define PVR2_CLIENT_ID_WM8775 6
+#define PVR2_CLIENT_ID_DEMOD 7
+
+struct pvr2_device_client_desc {
+ /* One ovr PVR2_CLIENT_ID_xxxx */
+ unsigned char module_id;
+
+ /* Null-terminated array of I2C addresses to try in order
+ initialize the module. It's safe to make this null terminated
+ since we're never going to encounter an i2c device with an
+ address of zero. If this is a null pointer or zero-length,
+ then no I2C addresses have been specified, in which case we'll
+ try some compiled in defaults for now. */
+ unsigned char *i2c_address_list;
+};
+
+struct pvr2_device_client_table {
+ const struct pvr2_device_client_desc *lst;
+ unsigned char cnt;
+};
+
+
struct pvr2_string_table {
const char **lst;
unsigned int cnt;
@@ -40,6 +68,7 @@ struct pvr2_string_table {
#define PVR2_ROUTING_SCHEME_HAUPPAUGE 0
#define PVR2_ROUTING_SCHEME_GOTVIEW 1
+#define PVR2_ROUTING_SCHEME_ONAIR 2
#define PVR2_DIGITAL_SCHEME_NONE 0
#define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1
@@ -66,6 +95,9 @@ struct pvr2_device_desc {
/* List of additional client modules we need to load */
struct pvr2_string_table client_modules;
+ /* List of defined client modules we need to load */
+ struct pvr2_device_client_table client_table;
+
/* List of FX2 firmware file names we should search; if empty then
FX2 firmware check / load is skipped and we assume the device
was initialized from internal ROM. */
@@ -73,7 +105,7 @@ struct pvr2_device_desc {
#ifdef CONFIG_VIDEO_PVRUSB2_DVB
/* callback functions to handle attachment of digital tuner & demod */
- struct pvr2_dvb_props *dvb_props;
+ const struct pvr2_dvb_props *dvb_props;
#endif
/* Initial standard bits to use for this device, if not zero.
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c
index 29d18e867..14decf216 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c
@@ -326,7 +326,7 @@ static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap)
static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
{
struct pvr2_hdw *hdw = adap->channel.hdw;
- struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props;
+ const struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props;
int ret = 0;
if (dvb_props == NULL) {
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index d96f0f510..5d75eb521 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -38,6 +38,7 @@
#include <linux/mutex.h>
#include "pvrusb2-hdw.h"
#include "pvrusb2-io.h"
+#include <media/v4l2-device.h>
#include <media/cx2341x.h>
#include "pvrusb2-devattr.h"
@@ -57,8 +58,6 @@
#define LOCK_TAKE(x) do { mutex_lock(&x##_mutex); x##_held = !0; } while (0)
#define LOCK_GIVE(x) do { x##_held = 0; mutex_unlock(&x##_mutex); } while (0)
-struct pvr2_decoder;
-
typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *);
typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *);
typedef int (*pvr2_ctlf_check_value)(struct pvr2_ctrl *,int);
@@ -139,22 +138,6 @@ struct pvr2_ctrl {
};
-struct pvr2_decoder_ctrl {
- void *ctxt;
- void (*detach)(void *);
- void (*enable)(void *,int);
- void (*force_reset)(void *);
-};
-
-#define PVR2_I2C_PEND_DETECT 0x01 /* Need to detect a client type */
-#define PVR2_I2C_PEND_CLIENT 0x02 /* Client needs a specific update */
-#define PVR2_I2C_PEND_REFRESH 0x04 /* Client has specific pending bits */
-#define PVR2_I2C_PEND_STALE 0x08 /* Broadcast pending bits */
-
-#define PVR2_I2C_PEND_ALL (PVR2_I2C_PEND_DETECT |\
- PVR2_I2C_PEND_CLIENT |\
- PVR2_I2C_PEND_REFRESH |\
- PVR2_I2C_PEND_STALE)
/* Disposition of firmware1 loading situation */
#define FW1_STATE_UNKNOWN 0
@@ -179,6 +162,8 @@ struct pvr2_hdw {
struct usb_device *usb_dev;
struct usb_interface *usb_intf;
+ /* Our handle into the v4l2 sub-device architecture */
+ struct v4l2_device v4l2_dev;
/* Device description, anything that must adjust behavior based on
device specific info will use information held here. */
const struct pvr2_device_desc *hdw_desc;
@@ -186,7 +171,6 @@ struct pvr2_hdw {
/* Kernel worker thread handling */
struct workqueue_struct *workqueue;
struct work_struct workpoll; /* Update driver state */
- struct work_struct worki2csync; /* Update i2c clients */
/* Video spigot */
struct pvr2_stream *vid_stream;
@@ -215,12 +199,6 @@ struct pvr2_hdw {
pvr2_i2c_func i2c_func[PVR2_I2C_FUNC_CNT];
int i2c_cx25840_hack_state;
int i2c_linked;
- unsigned int i2c_pend_types; /* Which types of update are needed */
- unsigned long i2c_pend_mask; /* Change bits we need to scan */
- unsigned long i2c_stale_mask; /* Pending broadcast change bits */
- unsigned long i2c_active_mask; /* All change bits currently in use */
- struct list_head i2c_clients;
- struct mutex i2c_list_lock;
/* Frequency table */
unsigned int freqTable[FREQTABLE_SIZE];
@@ -287,6 +265,7 @@ struct pvr2_hdw {
wait_queue_head_t state_wait_data;
+ int force_dirty; /* consider all controls dirty if true */
int flag_ok; /* device in known good state */
int flag_disconnected; /* flag_ok == 0 due to disconnect */
int flag_init_ok; /* true if structure is fully initialized */
@@ -295,17 +274,13 @@ struct pvr2_hdw {
int flag_decoder_missed;/* We've noticed missing decoder */
int flag_tripped; /* Indicates overall failure to start */
- struct pvr2_decoder_ctrl *decoder_ctrl;
+ unsigned int decoder_client_id;
// CPU firmware info (used to help find / save firmware data)
char *fw_buffer;
unsigned int fw_size;
int fw_cpu_flag; /* True if we are dealing with the CPU */
- // True if there is a request to trigger logging of state in each
- // module.
- int log_requested;
-
/* Tuner / frequency control stuff */
unsigned int tuner_type;
int tuner_updated;
@@ -403,7 +378,8 @@ struct pvr2_hdw {
/* This function gets the current frequency */
unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *);
-void pvr2_hdw_set_decoder(struct pvr2_hdw *,struct pvr2_decoder_ctrl *);
+
+void pvr2_hdw_status_poll(struct pvr2_hdw *);
#endif /* __PVRUSB2_HDW_INTERNAL_H */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 19e12c5aa..bea17cd64 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -24,17 +24,22 @@
#include <linux/firmware.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
+#include <media/tuner.h>
#include "pvrusb2.h"
#include "pvrusb2-std.h"
#include "pvrusb2-util.h"
#include "pvrusb2-hdw.h"
#include "pvrusb2-i2c-core.h"
-#include "pvrusb2-tuner.h"
#include "pvrusb2-eeprom.h"
#include "pvrusb2-hdw-internal.h"
#include "pvrusb2-encoder.h"
#include "pvrusb2-debug.h"
#include "pvrusb2-fx2-cmd.h"
+#include "pvrusb2-wm8775.h"
+#include "pvrusb2-video-v4l.h"
+#include "pvrusb2-cx2584x-v4l.h"
+#include "pvrusb2-cs53l32a.h"
+#include "pvrusb2-audio.h"
#include "compat.h"
#define TV_MIN_FREQ 55250000L
@@ -105,6 +110,39 @@ MODULE_PARM_DESC(radio_freq, "specify initial radio frequency");
/* size of a firmware chunk */
#define FIRMWARE_CHUNK_SIZE 0x2000
+typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *,
+ struct v4l2_subdev *);
+
+static const pvr2_subdev_update_func pvr2_module_update_functions[] = {
+ [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_subdev_update,
+ [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update,
+ [PVR2_CLIENT_ID_MSP3400] = pvr2_msp3400_subdev_update,
+ [PVR2_CLIENT_ID_CX25840] = pvr2_cx25840_subdev_update,
+ [PVR2_CLIENT_ID_CS53L32A] = pvr2_cs53l32a_subdev_update,
+};
+
+static const char *module_names[] = {
+ [PVR2_CLIENT_ID_MSP3400] = "msp3400",
+ [PVR2_CLIENT_ID_CX25840] = "cx25840",
+ [PVR2_CLIENT_ID_SAA7115] = "saa7115",
+ [PVR2_CLIENT_ID_TUNER] = "tuner",
+ [PVR2_CLIENT_ID_DEMOD] = "tuner",
+ [PVR2_CLIENT_ID_CS53L32A] = "cs53l32a",
+ [PVR2_CLIENT_ID_WM8775] = "wm8775",
+};
+
+
+static const unsigned char *module_i2c_addresses[] = {
+ [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63",
+ [PVR2_CLIENT_ID_DEMOD] = "\x43",
+ [PVR2_CLIENT_ID_MSP3400] = "\x40",
+ [PVR2_CLIENT_ID_SAA7115] = "\x21",
+ [PVR2_CLIENT_ID_WM8775] = "\x1b",
+ [PVR2_CLIENT_ID_CX25840] = "\x44",
+ [PVR2_CLIENT_ID_CS53L32A] = "\x11",
+};
+
+
/* Define the list of additional controls we'll dynamically construct based
on query of the cx2341x module. */
struct pvr2_mpeg_ids {
@@ -278,7 +316,6 @@ static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v);
static void pvr2_hdw_state_sched(struct pvr2_hdw *);
static int pvr2_hdw_state_eval(struct pvr2_hdw *);
static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long);
-static void pvr2_hdw_worker_i2c(struct work_struct *work);
static void pvr2_hdw_worker_poll(struct work_struct *work);
static int pvr2_hdw_wait(struct pvr2_hdw *,int state);
static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *);
@@ -643,7 +680,7 @@ static int ctrl_freq_max_get(struct pvr2_ctrl *cptr, int *vp)
unsigned long fv;
struct pvr2_hdw *hdw = cptr->hdw;
if (hdw->tuner_signal_stale) {
- pvr2_i2c_core_status_poll(hdw);
+ pvr2_hdw_status_poll(hdw);
}
fv = hdw->tuner_signal_info.rangehigh;
if (!fv) {
@@ -665,7 +702,7 @@ static int ctrl_freq_min_get(struct pvr2_ctrl *cptr, int *vp)
unsigned long fv;
struct pvr2_hdw *hdw = cptr->hdw;
if (hdw->tuner_signal_stale) {
- pvr2_i2c_core_status_poll(hdw);
+ pvr2_hdw_status_poll(hdw);
}
fv = hdw->tuner_signal_info.rangelow;
if (!fv) {
@@ -859,7 +896,7 @@ static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr)
static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp)
{
struct pvr2_hdw *hdw = cptr->hdw;
- pvr2_i2c_core_status_poll(hdw);
+ pvr2_hdw_status_poll(hdw);
*vp = hdw->tuner_signal_info.signal;
return 0;
}
@@ -869,7 +906,7 @@ static int ctrl_audio_modes_present_get(struct pvr2_ctrl *cptr,int *vp)
int val = 0;
unsigned int subchan;
struct pvr2_hdw *hdw = cptr->hdw;
- pvr2_i2c_core_status_poll(hdw);
+ pvr2_hdw_status_poll(hdw);
subchan = hdw->tuner_signal_info.rxsubchans;
if (subchan & V4L2_TUNER_SUB_MONO) {
val |= (1 << V4L2_TUNER_MODE_MONO);
@@ -1650,33 +1687,27 @@ static const char *pvr2_get_state_name(unsigned int st)
static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl)
{
- if (!hdw->decoder_ctrl) {
- if (!hdw->flag_decoder_missed) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "WARNING: No decoder present");
- hdw->flag_decoder_missed = !0;
- trace_stbit("flag_decoder_missed",
- hdw->flag_decoder_missed);
- }
- return -EIO;
+ /* Even though we really only care about the video decoder chip at
+ this point, we'll broadcast stream on/off to all sub-devices
+ anyway, just in case somebody else wants to hear the
+ command... */
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 stream=%s",
+ (enablefl ? "on" : "off"));
+ v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl);
+ if (hdw->decoder_client_id) {
+ /* We get here if the encoder has been noticed. Otherwise
+ we'll issue a warning to the user (which should
+ normally never happen). */
+ return 0;
}
- hdw->decoder_ctrl->enable(hdw->decoder_ctrl->ctxt,enablefl);
- return 0;
-}
-
-
-void pvr2_hdw_set_decoder(struct pvr2_hdw *hdw,struct pvr2_decoder_ctrl *ptr)
-{
- if (hdw->decoder_ctrl == ptr) return;
- hdw->decoder_ctrl = ptr;
- if (hdw->decoder_ctrl && hdw->flag_decoder_missed) {
- hdw->flag_decoder_missed = 0;
+ if (!hdw->flag_decoder_missed) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "WARNING: No decoder present");
+ hdw->flag_decoder_missed = !0;
trace_stbit("flag_decoder_missed",
hdw->flag_decoder_missed);
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Decoder has appeared");
- pvr2_hdw_state_sched(hdw);
}
+ return -EIO;
}
@@ -1950,6 +1981,166 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
}
+static unsigned int pvr2_copy_i2c_addr_list(
+ unsigned short *dst, const unsigned char *src,
+ unsigned int dst_max)
+{
+ unsigned int cnt = 0;
+ if (!src) return 0;
+ while (src[cnt] && (cnt + 1) < dst_max) {
+ dst[cnt] = src[cnt];
+ cnt++;
+ }
+ dst[cnt] = I2C_CLIENT_END;
+ return cnt;
+}
+
+
+static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw,
+ const struct pvr2_device_client_desc *cd)
+{
+ const char *fname;
+ unsigned char mid;
+ struct v4l2_subdev *sd;
+ unsigned int i2ccnt;
+ const unsigned char *p;
+ /* Arbitrary count - max # i2c addresses we will probe */
+ unsigned short i2caddr[25];
+
+ mid = cd->module_id;
+ fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL;
+ if (!fname) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Module ID %u for device %s has no name",
+ mid,
+ hdw->hdw_desc->description);
+ return -EINVAL;
+ }
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Module ID %u (%s) for device %s being loaded...",
+ mid, fname,
+ hdw->hdw_desc->description);
+
+ i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list,
+ ARRAY_SIZE(i2caddr));
+ if (!i2ccnt && ((p = (mid < ARRAY_SIZE(module_i2c_addresses)) ?
+ module_i2c_addresses[mid] : NULL) != NULL)) {
+ /* Second chance: Try default i2c address list */
+ i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, p,
+ ARRAY_SIZE(i2caddr));
+ if (i2ccnt) {
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Module ID %u:"
+ " Using default i2c address list",
+ mid);
+ }
+ }
+
+ if (!i2ccnt) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Module ID %u (%s) for device %s:"
+ " No i2c addresses",
+ mid, fname, hdw->hdw_desc->description);
+ return -EINVAL;
+ }
+
+ /* Note how the 2nd and 3rd arguments are the same for both
+ * v4l2_i2c_new_subdev() and v4l2_i2c_new_probed_subdev(). Why?
+ * Well the 2nd argument is the module name to load, while the 3rd
+ * argument is documented in the framework as being the "chipid" -
+ * and every other place where I can find examples of this, the
+ * "chipid" appears to just be the module name again. So here we
+ * just do the same thing. */
+ if (i2ccnt == 1) {
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Module ID %u:"
+ " Setting up with specified i2c address 0x%x",
+ mid, i2caddr[0]);
+ sd = v4l2_i2c_new_subdev(&hdw->i2c_adap,
+ fname, fname,
+ i2caddr[0]);
+ } else {
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Module ID %u:"
+ " Setting up with address probe list",
+ mid);
+ sd = v4l2_i2c_new_probed_subdev(&hdw->i2c_adap,
+ fname, fname,
+ i2caddr);
+ }
+
+ if (!sd) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Module ID %u (%s) for device %s failed to load",
+ mid, fname, hdw->hdw_desc->description);
+ return -EIO;
+ }
+
+ /* Tag this sub-device instance with the module ID we know about.
+ In other places we'll use that tag to determine if the instance
+ requires special handling. */
+ sd->grp_id = mid;
+
+ pvr2_trace(PVR2_TRACE_INFO, "Attached sub-driver %s", fname);
+
+
+ /* client-specific setup... */
+ switch (mid) {
+ case PVR2_CLIENT_ID_CX25840:
+ hdw->decoder_client_id = mid;
+ {
+ /*
+ Mike Isely <isely@pobox.com> 19-Nov-2006 - This
+ bit of nuttiness for cx25840 causes that module
+ to correctly set up its video scaling. This is
+ really a problem in the cx25840 module itself,
+ but we work around it here. The problem has not
+ been seen in ivtv because there VBI is supported
+ and set up. We don't do VBI here (at least not
+ yet) and thus we never attempted to even set it
+ up.
+ */
+ struct v4l2_format fmt;
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Module ID %u:"
+ " Executing cx25840 VBI hack",
+ mid);
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+ v4l2_device_call_all(&hdw->v4l2_dev, mid,
+ video, s_fmt, &fmt);
+ }
+ break;
+ case PVR2_CLIENT_ID_SAA7115:
+ hdw->decoder_client_id = mid;
+ break;
+ default: break;
+ }
+
+ return 0;
+}
+
+
+static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw)
+{
+ unsigned int idx;
+ const struct pvr2_string_table *cm;
+ const struct pvr2_device_client_table *ct;
+ int okFl = !0;
+
+ cm = &hdw->hdw_desc->client_modules;
+ for (idx = 0; idx < cm->cnt; idx++) {
+ request_module(cm->lst[idx]);
+ }
+
+ ct = &hdw->hdw_desc->client_table;
+ for (idx = 0; idx < ct->cnt; idx++) {
+ if (pvr2_hdw_load_subdev(hdw, &ct->lst[idx]) < 0) okFl = 0;
+ }
+ if (!okFl) pvr2_hdw_render_useless(hdw);
+}
+
+
static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
{
int ret;
@@ -1989,9 +2180,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
if (!pvr2_hdw_dev_ok(hdw)) return;
- for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) {
- request_module(hdw->hdw_desc->client_modules.lst[idx]);
- }
+ hdw->force_dirty = !0;
if (!hdw->hdw_desc->flag_no_powerup) {
pvr2_hdw_cmd_powerup(hdw);
@@ -2010,6 +2199,11 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
pvr2_i2c_core_init(hdw);
if (!pvr2_hdw_dev_ok(hdw)) return;
+ pvr2_hdw_load_modules(hdw);
+ if (!pvr2_hdw_dev_ok(hdw)) return;
+
+ v4l2_device_call_all(&hdw->v4l2_dev, 0, core, init, 0);
+
for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
cptr = hdw->controls + idx;
if (cptr->info->skip_init) continue;
@@ -2068,8 +2262,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
hdw->tuner_type);
}
- pvr2_i2c_core_check_stale(hdw);
- hdw->tuner_updated = 0;
if (!pvr2_hdw_dev_ok(hdw)) return;
@@ -2207,11 +2399,14 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
struct pvr2_hdw *hdw = NULL;
int valid_std_mask;
struct pvr2_ctrl *cptr;
+ struct usb_device *usb_dev;
const struct pvr2_device_desc *hdw_desc;
__u8 ifnum;
struct v4l2_queryctrl qctrl;
struct pvr2_ctl_info *ciptr;
+ usb_dev = interface_to_usbdev(intf);
+
hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info);
if (hdw_desc == NULL) {
@@ -2396,6 +2591,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL);
if (!hdw->ctl_read_urb) goto fail;
+ if (v4l2_device_register(&usb_dev->dev, &hdw->v4l2_dev) != 0) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Error registering with v4l core, giving up");
+ goto fail;
+ }
mutex_lock(&pvr2_unit_mtx); do {
for (idx = 0; idx < PVR_NUM; idx++) {
if (unit_pointers[idx]) continue;
@@ -2420,11 +2620,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
INIT_WORK(&hdw->workpoll,(void (*)(void*))pvr2_hdw_worker_poll,
&hdw->workpoll);
- INIT_WORK(&hdw->worki2csync,(void (*)(void*))pvr2_hdw_worker_i2c,
- &hdw->worki2csync);
#else
INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll);
- INIT_WORK(&hdw->worki2csync,pvr2_hdw_worker_i2c);
#endif
pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
@@ -2434,7 +2631,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
hdw->flag_ok = !0;
hdw->usb_intf = intf;
- hdw->usb_dev = interface_to_usbdev(intf);
+ hdw->usb_dev = usb_dev;
usb_make_path(hdw->usb_dev, hdw->bus_info, sizeof(hdw->bus_info));
@@ -2494,6 +2691,10 @@ static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw)
hdw->ctl_write_buffer = NULL;
}
hdw->flag_disconnected = !0;
+ /* If we don't do this, then there will be a dangling struct device
+ reference to our disappearing device persisting inside the V4L
+ core... */
+ v4l2_device_disconnect(&hdw->v4l2_dev);
hdw->usb_dev = NULL;
hdw->usb_intf = NULL;
pvr2_hdw_render_useless(hdw);
@@ -2521,10 +2722,8 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
pvr2_stream_destroy(hdw->vid_stream);
hdw->vid_stream = NULL;
}
- if (hdw->decoder_ctrl) {
- hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt);
- }
pvr2_i2c_core_done(hdw);
+ v4l2_device_unregister(&hdw->v4l2_dev);
pvr2_hdw_remove_usb_stuff(hdw);
mutex_lock(&pvr2_unit_mtx); do {
if ((hdw->unit_number >= 0) &&
@@ -2718,6 +2917,150 @@ static const char *get_ctrl_typename(enum pvr2_ctl_type tp)
}
+static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id,
+ const char *name, int val)
+{
+ struct v4l2_control ctrl;
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 %s=%d", name, val);
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.id = id;
+ ctrl.value = val;
+ v4l2_device_call_all(&hdw->v4l2_dev, 0, core, s_ctrl, &ctrl);
+}
+
+#define PVR2_SUBDEV_SET_CONTROL(hdw, id, lab) \
+ if ((hdw)->lab##_dirty || (hdw)->force_dirty) { \
+ pvr2_subdev_set_control(hdw, id, #lab, (hdw)->lab##_val); \
+ }
+
+/* Execute whatever commands are required to update the state of all the
+ sub-devices so that they match our current control values. */
+static void pvr2_subdev_update(struct pvr2_hdw *hdw)
+{
+ struct v4l2_subdev *sd;
+ unsigned int id;
+ pvr2_subdev_update_func fp;
+
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev update...");
+
+ if (hdw->tuner_updated || hdw->force_dirty) {
+ struct tuner_setup setup;
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev tuner set_type(%d)",
+ hdw->tuner_type);
+ if (((int)(hdw->tuner_type)) >= 0) {
+ setup.addr = ADDR_UNSET;
+ setup.type = hdw->tuner_type;
+ setup.mode_mask = T_RADIO | T_ANALOG_TV;
+ v4l2_device_call_all(&hdw->v4l2_dev, 0,
+ tuner, s_type_addr, &setup);
+ }
+ }
+
+ if (hdw->input_dirty || hdw->std_dirty || hdw->force_dirty) {
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_standard");
+ if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+ v4l2_device_call_all(&hdw->v4l2_dev, 0,
+ tuner, s_radio);
+ } else {
+ v4l2_std_id vs;
+ vs = hdw->std_mask_cur;
+ v4l2_device_call_all(&hdw->v4l2_dev, 0,
+ tuner, s_std, vs);
+ }
+ hdw->tuner_signal_stale = !0;
+ hdw->cropcap_stale = !0;
+ }
+
+ PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_BRIGHTNESS, brightness);
+ PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_CONTRAST, contrast);
+ PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_SATURATION, saturation);
+ PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_HUE, hue);
+ PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_MUTE, mute);
+ PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_VOLUME, volume);
+ PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BALANCE, balance);
+ PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BASS, bass);
+ PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_TREBLE, treble);
+
+ if (hdw->input_dirty || hdw->audiomode_dirty || hdw->force_dirty) {
+ struct v4l2_tuner vt;
+ memset(&vt, 0, sizeof(vt));
+ vt.audmode = hdw->audiomode_val;
+ v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt);
+ }
+
+ if (hdw->freqDirty || hdw->force_dirty) {
+ unsigned long fv;
+ struct v4l2_frequency freq;
+ fv = pvr2_hdw_get_cur_freq(hdw);
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_freq(%lu)", fv);
+ if (hdw->tuner_signal_stale) pvr2_hdw_status_poll(hdw);
+ memset(&freq, 0, sizeof(freq));
+ if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
+ /* ((fv * 1000) / 62500) */
+ freq.frequency = (fv * 2) / 125;
+ } else {
+ freq.frequency = fv / 62500;
+ }
+ /* tuner-core currently doesn't seem to care about this, but
+ let's set it anyway for completeness. */
+ if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+ freq.type = V4L2_TUNER_RADIO;
+ } else {
+ freq.type = V4L2_TUNER_ANALOG_TV;
+ }
+ freq.tuner = 0;
+ v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner,
+ s_frequency, &freq);
+ }
+
+ if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) {
+ struct v4l2_format fmt;
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.width = hdw->res_hor_val;
+ fmt.fmt.pix.height = hdw->res_ver_val;
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)",
+ fmt.fmt.pix.width, fmt.fmt.pix.height);
+ v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt);
+ }
+
+ if (hdw->srate_dirty || hdw->force_dirty) {
+ u32 val;
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d",
+ hdw->srate_val);
+ switch (hdw->srate_val) {
+ default:
+ case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
+ val = 48000;
+ break;
+ case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
+ val = 44100;
+ break;
+ case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
+ val = 32000;
+ break;
+ }
+ v4l2_device_call_all(&hdw->v4l2_dev, 0,
+ audio, s_clock_freq, val);
+ }
+
+ /* Unable to set crop parameters; there is apparently no equivalent
+ for VIDIOC_S_CROP */
+
+ v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
+ id = sd->grp_id;
+ if (id >= ARRAY_SIZE(pvr2_module_update_functions)) continue;
+ fp = pvr2_module_update_functions[id];
+ if (!fp) continue;
+ (*fp)(hdw, sd);
+ }
+
+ if (hdw->tuner_signal_stale || hdw->cropcap_stale) {
+ pvr2_hdw_status_poll(hdw);
+ }
+}
+
+
/* Figure out if we need to commit control changes. If so, mark internal
state flags to indicate this fact and return true. Otherwise do nothing
else and return false. */
@@ -2726,7 +3069,7 @@ static int pvr2_hdw_commit_setup(struct pvr2_hdw *hdw)
unsigned int idx;
struct pvr2_ctrl *cptr;
int value;
- int commit_flag = 0;
+ int commit_flag = hdw->force_dirty;
char buf[100];
unsigned int bcnt,ccnt;
@@ -2882,18 +3225,6 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,VIDIOC_S_EXT_CTRLS);
}
- /* Scan i2c core at this point - before we clear all the dirty
- bits. Various parts of the i2c core will notice dirty bits as
- appropriate and arrange to broadcast or directly send updates to
- the client drivers in order to keep everything in sync */
- pvr2_i2c_core_check_stale(hdw);
-
- for (idx = 0; idx < hdw->control_cnt; idx++) {
- cptr = hdw->controls + idx;
- if (!cptr->info->clear_dirty) continue;
- cptr->info->clear_dirty(cptr);
- }
-
if (hdw->active_stream_type != hdw->desired_stream_type) {
/* Handle any side effects of stream config here */
hdw->active_stream_type = hdw->desired_stream_type;
@@ -2913,8 +3244,16 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
}
}
- /* Now execute i2c core update */
- pvr2_i2c_core_sync(hdw);
+ /* Check and update state for all sub-devices. */
+ pvr2_subdev_update(hdw);
+
+ hdw->tuner_updated = 0;
+ hdw->force_dirty = 0;
+ for (idx = 0; idx < hdw->control_cnt; idx++) {
+ cptr = hdw->controls + idx;
+ if (!cptr->info->clear_dirty) continue;
+ cptr->info->clear_dirty(cptr);
+ }
if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) &&
hdw->state_encoder_run) {
@@ -2944,15 +3283,6 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw)
}
-static void pvr2_hdw_worker_i2c(struct work_struct *work)
-{
- struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,worki2csync);
- LOCK_TAKE(hdw->big_lock); do {
- pvr2_i2c_core_sync(hdw);
- } while (0); LOCK_GIVE(hdw->big_lock);
-}
-
-
static void pvr2_hdw_worker_poll(struct work_struct *work)
{
int fl = 0;
@@ -3013,7 +3343,7 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw)
{
LOCK_TAKE(hdw->big_lock); do {
- pvr2_i2c_core_status_poll(hdw);
+ pvr2_hdw_status_poll(hdw);
} while (0); LOCK_GIVE(hdw->big_lock);
}
@@ -3023,7 +3353,7 @@ static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw)
if (!hdw->cropcap_stale) {
return 0;
}
- pvr2_i2c_core_status_poll(hdw);
+ pvr2_hdw_status_poll(hdw);
if (hdw->cropcap_stale) {
return -EIO;
}
@@ -3050,7 +3380,7 @@ int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp)
{
LOCK_TAKE(hdw->big_lock); do {
if (hdw->tuner_signal_stale) {
- pvr2_i2c_core_status_poll(hdw);
+ pvr2_hdw_status_poll(hdw);
}
memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner));
} while (0); LOCK_GIVE(hdw->big_lock);
@@ -3069,11 +3399,8 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw)
{
int nr = pvr2_hdw_get_unit_number(hdw);
LOCK_TAKE(hdw->big_lock); do {
- hdw->log_requested = !0;
printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr);
- pvr2_i2c_core_check_stale(hdw);
- hdw->log_requested = 0;
- pvr2_i2c_core_sync(hdw);
+ v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status);
pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:");
cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2");
pvr2_hdw_state_log_state(hdw);
@@ -3828,22 +4155,16 @@ int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw)
int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
{
- if (!hdw->decoder_ctrl) {
- pvr2_trace(PVR2_TRACE_INIT,
- "Unable to reset decoder: nothing attached");
- return -ENOTTY;
- }
-
- if (!hdw->decoder_ctrl->force_reset) {
- pvr2_trace(PVR2_TRACE_INIT,
- "Unable to reset decoder: not implemented");
- return -ENOTTY;
- }
-
pvr2_trace(PVR2_TRACE_INIT,
"Requesting decoder reset");
- hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt);
- return 0;
+ if (hdw->decoder_client_id) {
+ v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
+ core, reset, 0);
+ return 0;
+ }
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Unable to reset decoder: nothing attached");
+ return -ENOTTY;
}
@@ -4588,6 +4909,79 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
}
+/* Generate report containing info about attached sub-devices and attached
+ i2c clients, including an indication of which attached i2c clients are
+ actually sub-devices. */
+static unsigned int pvr2_hdw_report_clients(struct pvr2_hdw *hdw,
+ char *buf, unsigned int acnt)
+{
+ struct v4l2_subdev *sd;
+ unsigned int tcnt = 0;
+ unsigned int ccnt;
+ struct i2c_client *client;
+ struct list_head *item;
+ void *cd;
+ const char *p;
+ unsigned int id;
+
+ ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers:");
+ tcnt += ccnt;
+ v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
+ id = sd->grp_id;
+ p = NULL;
+ if (id < ARRAY_SIZE(module_names)) p = module_names[id];
+ if (p) {
+ ccnt = scnprintf(buf + tcnt, acnt - tcnt, " %s", p);
+ tcnt += ccnt;
+ } else {
+ ccnt = scnprintf(buf + tcnt, acnt - tcnt,
+ " (unknown id=%u)", id);
+ tcnt += ccnt;
+ }
+ }
+ ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n");
+ tcnt += ccnt;
+
+ ccnt = scnprintf(buf + tcnt, acnt - tcnt, "I2C clients:\n");
+ tcnt += ccnt;
+
+ mutex_lock(&hdw->i2c_adap.clist_lock);
+ list_for_each(item, &hdw->i2c_adap.clients) {
+ client = list_entry(item, struct i2c_client, list);
+ ccnt = scnprintf(buf + tcnt, acnt - tcnt,
+ " %s: i2c=%02x", client->name, client->addr);
+ tcnt += ccnt;
+ cd = i2c_get_clientdata(client);
+ v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
+ if (cd == sd) {
+ id = sd->grp_id;
+ p = NULL;
+ if (id < ARRAY_SIZE(module_names)) {
+ p = module_names[id];
+ }
+ if (p) {
+ ccnt = scnprintf(buf + tcnt,
+ acnt - tcnt,
+ " subdev=%s", p);
+ tcnt += ccnt;
+ } else {
+ ccnt = scnprintf(buf + tcnt,
+ acnt - tcnt,
+ " subdev= id %u)",
+ id);
+ tcnt += ccnt;
+ }
+ break;
+ }
+ }
+ ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n");
+ tcnt += ccnt;
+ }
+ mutex_unlock(&hdw->i2c_adap.clist_lock);
+ return tcnt;
+}
+
+
unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw,
char *buf,unsigned int acnt)
{
@@ -4602,6 +4996,8 @@ unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw,
buf[0] = '\n'; ccnt = 1;
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
}
+ ccnt = pvr2_hdw_report_clients(hdw, buf, acnt);
+ bcnt += ccnt; acnt -= ccnt; buf += ccnt;
LOCK_GIVE(hdw->big_lock);
return bcnt;
}
@@ -4609,14 +5005,25 @@ unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw,
static void pvr2_hdw_state_log_state(struct pvr2_hdw *hdw)
{
- char buf[128];
- unsigned int idx,ccnt;
+ char buf[256];
+ unsigned int idx, ccnt;
+ unsigned int lcnt, ucnt;
for (idx = 0; ; idx++) {
ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,sizeof(buf));
if (!ccnt) break;
printk(KERN_INFO "%s %.*s\n",hdw->name,ccnt,buf);
}
+ ccnt = pvr2_hdw_report_clients(hdw, buf, sizeof(buf));
+ ucnt = 0;
+ while (ucnt < ccnt) {
+ lcnt = 0;
+ while ((lcnt + ucnt < ccnt) && (buf[lcnt + ucnt] != '\n')) {
+ lcnt++;
+ }
+ printk(KERN_INFO "%s %.*s\n", hdw->name, lcnt, buf + ucnt);
+ ucnt += lcnt + 1;
+ }
}
@@ -4796,6 +5203,30 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val)
}
+void pvr2_hdw_status_poll(struct pvr2_hdw *hdw)
+{
+ struct v4l2_tuner *vtp = &hdw->tuner_signal_info;
+ memset(vtp, 0, sizeof(*vtp));
+ hdw->tuner_signal_stale = 0;
+ /* Note: There apparently is no replacement for VIDIOC_CROPCAP
+ using v4l2-subdev - therefore we can't support that AT ALL right
+ now. (Of course, no sub-drivers seem to implement it either.
+ But now it's a a chicken and egg problem...) */
+ v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, g_tuner,
+ &hdw->tuner_signal_info);
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev status poll"
+ " type=%u strength=%u audio=0x%x cap=0x%x"
+ " low=%u hi=%u",
+ vtp->type,
+ vtp->signal, vtp->rxsubchans, vtp->capability,
+ vtp->rangelow, vtp->rangehigh);
+
+ /* We have to do this to avoid getting into constant polling if
+ there's nobody to answer a poll of cropcap info. */
+ hdw->cropcap_stale = 0;
+}
+
+
unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw)
{
return hdw->input_avail_mask;
@@ -4891,7 +5322,6 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
int setFl, u64 *val_ptr)
{
#ifdef CONFIG_VIDEO_ADV_DEBUG
- struct pvr2_i2c_client *cp;
struct v4l2_dbg_register req;
int stat = 0;
int okFl = 0;
@@ -4901,21 +5331,9 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
req.match = *match;
req.reg = reg_id;
if (setFl) req.val = *val_ptr;
- mutex_lock(&hdw->i2c_list_lock); do {
- list_for_each_entry(cp, &hdw->i2c_clients, list) {
- if (!v4l2_chip_match_i2c_client(
- cp->client,
- &req.match)) {
- continue;
- }
- stat = pvr2_i2c_client_cmd(
- cp,(setFl ? VIDIOC_DBG_S_REGISTER :
- VIDIOC_DBG_G_REGISTER),&req);
- if (!setFl) *val_ptr = req.val;
- okFl = !0;
- break;
- }
- } while (0); mutex_unlock(&hdw->i2c_list_lock);
+ /* It would be nice to know if a sub-device answered the request */
+ v4l2_device_call_all(&hdw->v4l2_dev, 0, core, g_register, &req);
+ if (!setFl) *val_ptr = req.val;
if (okFl) {
return stat;
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
deleted file mode 100644
index 073b02a4b..000000000
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- *
- *
- * Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *
- * 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
- *
- * 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 "pvrusb2-i2c-core.h"
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include "pvrusb2-i2c-cmd-v4l2.h"
-#include "pvrusb2-audio.h"
-#include "pvrusb2-tuner.h"
-#include "pvrusb2-video-v4l.h"
-#include "pvrusb2-cx2584x-v4l.h"
-#include "pvrusb2-wm8775.h"
-#include "compat.h"
-
-#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
-
-#define OP_INIT 0 /* MUST come first so it is run first */
-#define OP_STANDARD 1
-#define OP_AUDIOMODE 2
-#define OP_BCSH 3
-#define OP_VOLUME 4
-#define OP_FREQ 5
-#define OP_AUDIORATE 6
-#define OP_CROP 7
-#define OP_SIZE 8
-#define OP_LOG 9
-
-static const struct pvr2_i2c_op * const ops[] = {
- [OP_INIT] = &pvr2_i2c_op_v4l2_init,
- [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard,
- [OP_AUDIOMODE] = &pvr2_i2c_op_v4l2_audiomode,
- [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh,
- [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume,
- [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency,
- [OP_CROP] = &pvr2_i2c_op_v4l2_crop,
- [OP_SIZE] = &pvr2_i2c_op_v4l2_size,
- [OP_LOG] = &pvr2_i2c_op_v4l2_log,
-};
-
-void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
-{
- int id;
- id = cp->client->driver->id;
- cp->ctl_mask = ((1 << OP_INIT) |
- (1 << OP_STANDARD) |
- (1 << OP_AUDIOMODE) |
- (1 << OP_BCSH) |
- (1 << OP_VOLUME) |
- (1 << OP_FREQ) |
- (1 << OP_CROP) |
- (1 << OP_SIZE) |
- (1 << OP_LOG));
- cp->status_poll = pvr2_v4l2_cmd_status_poll;
-
- if (id == I2C_DRIVERID_MSP3400) {
- if (pvr2_i2c_msp3400_setup(hdw,cp)) {
- return;
- }
- }
- if (id == I2C_DRIVERID_TUNER) {
- if (pvr2_i2c_tuner_setup(hdw,cp)) {
- return;
- }
- }
- if (id == I2C_DRIVERID_CX25840) {
- if (pvr2_i2c_cx2584x_v4l_setup(hdw,cp)) {
- return;
- }
- }
- if (id == I2C_DRIVERID_WM8775) {
- if (pvr2_i2c_wm8775_setup(hdw,cp)) {
- return;
- }
- }
- if (id == I2C_DRIVERID_SAA711X) {
- if (pvr2_i2c_decoder_v4l_setup(hdw,cp)) {
- return;
- }
- }
-}
-
-
-const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx)
-{
- if (idx >= ARRAY_SIZE(ops))
- return NULL;
- return ops[idx];
-}
-
-
-/*
- Stuff for Emacs to see, in order to encourage consistent editing style:
- *** Local Variables: ***
- *** mode: c ***
- *** fill-column: 75 ***
- *** tab-width: 8 ***
- *** c-basic-offset: 8 ***
- *** End: ***
- */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
deleted file mode 100644
index db61c1fb0..000000000
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- *
- *
- * Copyright (C) 2005 Mike Isely <isely@pobox.com>
- * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- * 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
- *
- * 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 "pvrusb2-i2c-cmd-v4l2.h"
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include "compat.h"
-
-static void execute_init(struct pvr2_hdw *hdw)
-{
- u32 dummy = 0;
- pvr2_trace(PVR2_TRACE_CHIPS, "i2c v4l2 init");
- pvr2_i2c_core_cmd(hdw, VIDIOC_INT_INIT, &dummy);
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_init = {
- .update = execute_init,
- .name = "v4l2_init",
-};
-
-
-static void set_standard(struct pvr2_hdw *hdw)
-{
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_standard");
-
- if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
- pvr2_i2c_core_cmd(hdw,AUDC_SET_RADIO,NULL);
- } else {
- v4l2_std_id vs;
- vs = hdw->std_mask_cur;
- pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs);
- }
- hdw->tuner_signal_stale = !0;
- hdw->cropcap_stale = !0;
-}
-
-
-static int check_standard(struct pvr2_hdw *hdw)
-{
- return (hdw->input_dirty != 0) || (hdw->std_dirty != 0);
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard = {
- .check = check_standard,
- .update = set_standard,
- .name = "v4l2_standard",
-};
-
-
-static void set_bcsh(struct pvr2_hdw *hdw)
-{
- struct v4l2_control ctrl;
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_bcsh"
- " b=%d c=%d s=%d h=%d",
- hdw->brightness_val,hdw->contrast_val,
- hdw->saturation_val,hdw->hue_val);
- memset(&ctrl,0,sizeof(ctrl));
- ctrl.id = V4L2_CID_BRIGHTNESS;
- ctrl.value = hdw->brightness_val;
- pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
- ctrl.id = V4L2_CID_CONTRAST;
- ctrl.value = hdw->contrast_val;
- pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
- ctrl.id = V4L2_CID_SATURATION;
- ctrl.value = hdw->saturation_val;
- pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
- ctrl.id = V4L2_CID_HUE;
- ctrl.value = hdw->hue_val;
- pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
-}
-
-
-static int check_bcsh(struct pvr2_hdw *hdw)
-{
- return (hdw->brightness_dirty ||
- hdw->contrast_dirty ||
- hdw->saturation_dirty ||
- hdw->hue_dirty);
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh = {
- .check = check_bcsh,
- .update = set_bcsh,
- .name = "v4l2_bcsh",
-};
-
-
-static void set_volume(struct pvr2_hdw *hdw)
-{
- struct v4l2_control ctrl;
- pvr2_trace(PVR2_TRACE_CHIPS,
- "i2c v4l2 set_volume"
- "(vol=%d bal=%d bas=%d treb=%d mute=%d)",
- hdw->volume_val,
- hdw->balance_val,
- hdw->bass_val,
- hdw->treble_val,
- hdw->mute_val);
- memset(&ctrl,0,sizeof(ctrl));
- ctrl.id = V4L2_CID_AUDIO_MUTE;
- ctrl.value = hdw->mute_val ? 1 : 0;
- pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
- ctrl.id = V4L2_CID_AUDIO_VOLUME;
- ctrl.value = hdw->volume_val;
- pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
- ctrl.id = V4L2_CID_AUDIO_BALANCE;
- ctrl.value = hdw->balance_val;
- pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
- ctrl.id = V4L2_CID_AUDIO_BASS;
- ctrl.value = hdw->bass_val;
- pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
- ctrl.id = V4L2_CID_AUDIO_TREBLE;
- ctrl.value = hdw->treble_val;
- pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
-}
-
-
-static int check_volume(struct pvr2_hdw *hdw)
-{
- return (hdw->volume_dirty ||
- hdw->balance_dirty ||
- hdw->bass_dirty ||
- hdw->treble_dirty ||
- hdw->mute_dirty);
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume = {
- .check = check_volume,
- .update = set_volume,
- .name = "v4l2_volume",
-};
-
-
-static void set_audiomode(struct pvr2_hdw *hdw)
-{
- struct v4l2_tuner vt;
- memset(&vt,0,sizeof(vt));
- vt.audmode = hdw->audiomode_val;
- pvr2_i2c_core_cmd(hdw,VIDIOC_S_TUNER,&vt);
-}
-
-
-static int check_audiomode(struct pvr2_hdw *hdw)
-{
- return (hdw->input_dirty ||
- hdw->audiomode_dirty);
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode = {
- .check = check_audiomode,
- .update = set_audiomode,
- .name = "v4l2_audiomode",
-};
-
-
-static void set_frequency(struct pvr2_hdw *hdw)
-{
- unsigned long fv;
- struct v4l2_frequency freq;
- fv = pvr2_hdw_get_cur_freq(hdw);
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv);
- if (hdw->tuner_signal_stale) {
- pvr2_i2c_core_status_poll(hdw);
- }
- memset(&freq,0,sizeof(freq));
- if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
- // ((fv * 1000) / 62500)
- freq.frequency = (fv * 2) / 125;
- } else {
- freq.frequency = fv / 62500;
- }
- /* tuner-core currently doesn't seem to care about this, but
- let's set it anyway for completeness. */
- if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
- freq.type = V4L2_TUNER_RADIO;
- } else {
- freq.type = V4L2_TUNER_ANALOG_TV;
- }
- freq.tuner = 0;
- pvr2_i2c_core_cmd(hdw,VIDIOC_S_FREQUENCY,&freq);
-}
-
-
-static int check_frequency(struct pvr2_hdw *hdw)
-{
- return hdw->freqDirty != 0;
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency = {
- .check = check_frequency,
- .update = set_frequency,
- .name = "v4l2_freq",
-};
-
-
-static void set_size(struct pvr2_hdw *hdw)
-{
- struct v4l2_format fmt;
-
- memset(&fmt,0,sizeof(fmt));
-
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = hdw->res_hor_val;
- fmt.fmt.pix.height = hdw->res_ver_val;
-
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_size(%dx%d)",
- fmt.fmt.pix.width,fmt.fmt.pix.height);
-
- pvr2_i2c_core_cmd(hdw,VIDIOC_S_FMT,&fmt);
-}
-
-
-static int check_size(struct pvr2_hdw *hdw)
-{
- return (hdw->res_hor_dirty || hdw->res_ver_dirty);
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = {
- .check = check_size,
- .update = set_size,
- .name = "v4l2_size",
-};
-
-
-static void set_crop(struct pvr2_hdw *hdw)
-{
- struct v4l2_crop crop;
-
- memset(&crop, 0, sizeof crop);
- crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- crop.c.left = hdw->cropl_val;
- crop.c.top = hdw->cropt_val;
- crop.c.height = hdw->croph_val;
- crop.c.width = hdw->cropw_val;
-
- pvr2_trace(PVR2_TRACE_CHIPS,
- "i2c v4l2 set_crop crop=%d:%d:%d:%d",
- crop.c.width, crop.c.height, crop.c.left, crop.c.top);
-
- pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop);
-}
-
-static int check_crop(struct pvr2_hdw *hdw)
-{
- return (hdw->cropl_dirty || hdw->cropt_dirty ||
- hdw->cropw_dirty || hdw->croph_dirty);
-}
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = {
- .check = check_crop,
- .update = set_crop,
- .name = "v4l2_crop",
-};
-
-
-static void do_log(struct pvr2_hdw *hdw)
-{
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()");
- pvr2_i2c_core_cmd(hdw,VIDIOC_LOG_STATUS,NULL);
-
-}
-
-
-static int check_log(struct pvr2_hdw *hdw)
-{
- return hdw->log_requested != 0;
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log = {
- .check = check_log,
- .update = do_log,
- .name = "v4l2_log",
-};
-
-
-void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl)
-{
- pvr2_i2c_client_cmd(cp,
- (fl ? VIDIOC_STREAMON : VIDIOC_STREAMOFF),NULL);
-}
-
-
-void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp)
-{
- int stat;
- struct pvr2_hdw *hdw = cp->hdw;
- if (hdw->cropcap_stale) {
- hdw->cropcap_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- stat = pvr2_i2c_client_cmd(cp, VIDIOC_CROPCAP,
- &hdw->cropcap_info);
- if (stat == 0) {
- /* Check was successful, so the data is no
- longer considered stale. */
- hdw->cropcap_stale = 0;
- }
- }
- pvr2_i2c_client_cmd(cp, VIDIOC_G_TUNER, &hdw->tuner_signal_info);
-}
-
-
-/*
- Stuff for Emacs to see, in order to encourage consistent editing style:
- *** Local Variables: ***
- *** mode: c ***
- *** fill-column: 70 ***
- *** tab-width: 8 ***
- *** c-basic-offset: 8 ***
- *** End: ***
- */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
deleted file mode 100644
index 69a63f2a8..000000000
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- *
- * Copyright (C) 2005 Mike Isely <isely@pobox.com>
- * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- * 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
- *
- * 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 __PVRUSB2_CMD_V4L2_H
-#define __PVRUSB2_CMD_V4L2_H
-
-#include "pvrusb2-i2c-core.h"
-
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_init;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log;
-
-void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int);
-void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *);
-
-#endif /* __PVRUSB2_CMD_V4L2_H */
-
-/*
- Stuff for Emacs to see, in order to encourage consistent editing style:
- *** Local Variables: ***
- *** mode: c ***
- *** fill-column: 70 ***
- *** tab-width: 8 ***
- *** c-basic-offset: 8 ***
- *** End: ***
- */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index d95abcc55..fde4d3bd1 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -18,6 +18,7 @@
*
*/
+#include <linux/i2c.h>
#include "pvrusb2-i2c-core.h"
#include "pvrusb2-hdw-internal.h"
#include "pvrusb2-debug.h"
@@ -30,8 +31,7 @@
/*
This module attempts to implement a compliant I2C adapter for the pvrusb2
- device. By doing this we can then make use of existing functionality in
- V4L (e.g. tuner.c) rather than rolling our own.
+ device.
*/
@@ -43,10 +43,6 @@ static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 };
module_param_array(ir_mode, int, NULL, 0444);
MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR");
-static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
- unsigned int detail,
- char *buf,unsigned int maxlen);
-
static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */
u8 i2c_addr, /* I2C address we're talking to */
u8 *data, /* Data to write */
@@ -599,414 +595,13 @@ static u32 pvr2_i2c_functionality(struct i2c_adapter *adap)
return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
}
-static int pvr2_i2c_core_singleton(struct i2c_client *cp,
- unsigned int cmd,void *arg)
-{
- int stat;
- if (!cp) return -EINVAL;
- if (!(cp->driver)) return -EINVAL;
- if (!(cp->driver->command)) return -EINVAL;
- if (!try_module_get(cp->driver->driver.owner)) return -EAGAIN;
- stat = cp->driver->command(cp,cmd,arg);
- module_put(cp->driver->driver.owner);
- return stat;
-}
-
-int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg)
-{
- int stat;
- if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) {
- char buf[100];
- unsigned int cnt;
- cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG,
- buf,sizeof(buf));
- pvr2_trace(PVR2_TRACE_I2C_CMD,
- "i2c COMMAND (code=%u 0x%x) to %.*s",
- cmd,cmd,cnt,buf);
- }
- stat = pvr2_i2c_core_singleton(cp->client,cmd,arg);
- if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) {
- char buf[100];
- unsigned int cnt;
- cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG,
- buf,sizeof(buf));
- pvr2_trace(PVR2_TRACE_I2C_CMD,
- "i2c COMMAND to %.*s (ret=%d)",cnt,buf,stat);
- }
- return stat;
-}
-
-int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg)
-{
- struct pvr2_i2c_client *cp, *ncp;
- int stat = -EINVAL;
-
- if (!hdw) return stat;
-
- mutex_lock(&hdw->i2c_list_lock);
- list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
- if (!cp->recv_enable) continue;
- mutex_unlock(&hdw->i2c_list_lock);
- stat = pvr2_i2c_client_cmd(cp,cmd,arg);
- mutex_lock(&hdw->i2c_list_lock);
- }
- mutex_unlock(&hdw->i2c_list_lock);
- return stat;
-}
-
-
-static int handler_check(struct pvr2_i2c_client *cp)
-{
- struct pvr2_i2c_handler *hp = cp->handler;
- if (!hp) return 0;
- if (!hp->func_table->check) return 0;
- return hp->func_table->check(hp->func_data) != 0;
-}
-
-#define BUFSIZE 500
-
-
-void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw)
-{
- struct pvr2_i2c_client *cp;
- mutex_lock(&hdw->i2c_list_lock); do {
- struct v4l2_tuner *vtp = &hdw->tuner_signal_info;
- memset(vtp,0,sizeof(*vtp));
- list_for_each_entry(cp, &hdw->i2c_clients, list) {
- if (!cp->detected_flag) continue;
- if (!cp->status_poll) continue;
- cp->status_poll(cp);
- }
- hdw->tuner_signal_stale = 0;
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c status poll"
- " type=%u strength=%u audio=0x%x cap=0x%x"
- " low=%u hi=%u",
- vtp->type,
- vtp->signal,vtp->rxsubchans,vtp->capability,
- vtp->rangelow,vtp->rangehigh);
- } while (0); mutex_unlock(&hdw->i2c_list_lock);
-}
-
-
-/* Issue various I2C operations to bring chip-level drivers into sync with
- state stored in this driver. */
-void pvr2_i2c_core_sync(struct pvr2_hdw *hdw)
-{
- unsigned long msk;
- unsigned int idx;
- struct pvr2_i2c_client *cp, *ncp;
-
- if (!hdw->i2c_linked) return;
- if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) {
- return;
- }
- mutex_lock(&hdw->i2c_list_lock); do {
- pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync BEGIN");
- if (hdw->i2c_pend_types & PVR2_I2C_PEND_DETECT) {
- /* One or more I2C clients have attached since we
- last synced. So scan the list and identify the
- new clients. */
- char *buf;
- unsigned int cnt;
- unsigned long amask = 0;
- buf = kmalloc(BUFSIZE,GFP_KERNEL);
- pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT");
- hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT;
- list_for_each_entry(cp, &hdw->i2c_clients, list) {
- if (!cp->detected_flag) {
- cp->ctl_mask = 0;
- pvr2_i2c_probe(hdw,cp);
- cp->detected_flag = !0;
- msk = cp->ctl_mask;
- cnt = 0;
- if (buf) {
- cnt = pvr2_i2c_client_describe(
- cp,
- PVR2_I2C_DETAIL_ALL,
- buf,BUFSIZE);
- }
- trace_i2c("Probed: %.*s",cnt,buf);
- if (handler_check(cp)) {
- hdw->i2c_pend_types |=
- PVR2_I2C_PEND_CLIENT;
- }
- cp->pend_mask = msk;
- hdw->i2c_pend_mask |= msk;
- hdw->i2c_pend_types |=
- PVR2_I2C_PEND_REFRESH;
- }
- amask |= cp->ctl_mask;
- }
- hdw->i2c_active_mask = amask;
- if (buf) kfree(buf);
- }
- if (hdw->i2c_pend_types & PVR2_I2C_PEND_STALE) {
- /* Need to do one or more global updates. Arrange
- for this to happen. */
- unsigned long m2;
- pvr2_trace(PVR2_TRACE_I2C_CORE,
- "i2c: PEND_STALE (0x%lx)",
- hdw->i2c_stale_mask);
- hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE;
- list_for_each_entry(cp, &hdw->i2c_clients, list) {
- m2 = hdw->i2c_stale_mask;
- m2 &= cp->ctl_mask;
- m2 &= ~cp->pend_mask;
- if (m2) {
- pvr2_trace(PVR2_TRACE_I2C_CORE,
- "i2c: cp=%p setting 0x%lx",
- cp,m2);
- cp->pend_mask |= m2;
- }
- }
- hdw->i2c_pend_mask |= hdw->i2c_stale_mask;
- hdw->i2c_stale_mask = 0;
- hdw->i2c_pend_types |= PVR2_I2C_PEND_REFRESH;
- }
- if (hdw->i2c_pend_types & PVR2_I2C_PEND_CLIENT) {
- /* One or more client handlers are asking for an
- update. Run through the list of known clients
- and update each one. */
- pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT");
- hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT;
- list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients,
- list) {
- if (!cp->handler) continue;
- if (!cp->handler->func_table->update) continue;
- pvr2_trace(PVR2_TRACE_I2C_CORE,
- "i2c: cp=%p update",cp);
- mutex_unlock(&hdw->i2c_list_lock);
- cp->handler->func_table->update(
- cp->handler->func_data);
- mutex_lock(&hdw->i2c_list_lock);
- /* If client's update function set some
- additional pending bits, account for that
- here. */
- if (cp->pend_mask & ~hdw->i2c_pend_mask) {
- hdw->i2c_pend_mask |= cp->pend_mask;
- hdw->i2c_pend_types |=
- PVR2_I2C_PEND_REFRESH;
- }
- }
- }
- if (hdw->i2c_pend_types & PVR2_I2C_PEND_REFRESH) {
- const struct pvr2_i2c_op *opf;
- unsigned long pm;
- /* Some actual updates are pending. Walk through
- each update type and perform it. */
- pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_REFRESH"
- " (0x%lx)",hdw->i2c_pend_mask);
- hdw->i2c_pend_types &= ~PVR2_I2C_PEND_REFRESH;
- pm = hdw->i2c_pend_mask;
- hdw->i2c_pend_mask = 0;
- for (idx = 0, msk = 1; pm; idx++, msk <<= 1) {
- if (!(pm & msk)) continue;
- pm &= ~msk;
- list_for_each_entry(cp, &hdw->i2c_clients,
- list) {
- if (cp->pend_mask & msk) {
- cp->pend_mask &= ~msk;
- cp->recv_enable = !0;
- } else {
- cp->recv_enable = 0;
- }
- }
- opf = pvr2_i2c_get_op(idx);
- if (!opf) continue;
- mutex_unlock(&hdw->i2c_list_lock);
- opf->update(hdw);
- mutex_lock(&hdw->i2c_list_lock);
- }
- }
- pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync END");
- } while (0); mutex_unlock(&hdw->i2c_list_lock);
-}
-
-int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw)
-{
- unsigned long msk,sm,pm;
- unsigned int idx;
- const struct pvr2_i2c_op *opf;
- struct pvr2_i2c_client *cp;
- unsigned int pt = 0;
-
- pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale BEGIN");
-
- pm = hdw->i2c_active_mask;
- sm = 0;
- for (idx = 0, msk = 1; pm; idx++, msk <<= 1) {
- if (!(msk & pm)) continue;
- pm &= ~msk;
- opf = pvr2_i2c_get_op(idx);
- if (!(opf && opf->check)) continue;
- if (opf->check(hdw)) {
- sm |= msk;
- }
- }
- if (sm) pt |= PVR2_I2C_PEND_STALE;
-
- list_for_each_entry(cp, &hdw->i2c_clients, list)
- if (handler_check(cp))
- pt |= PVR2_I2C_PEND_CLIENT;
-
- if (pt) {
- mutex_lock(&hdw->i2c_list_lock); do {
- hdw->i2c_pend_types |= pt;
- hdw->i2c_stale_mask |= sm;
- hdw->i2c_pend_mask |= hdw->i2c_stale_mask;
- } while (0); mutex_unlock(&hdw->i2c_list_lock);
- }
-
- pvr2_trace(PVR2_TRACE_I2C_CORE,
- "i2c: types=0x%x stale=0x%lx pend=0x%lx",
- hdw->i2c_pend_types,
- hdw->i2c_stale_mask,
- hdw->i2c_pend_mask);
- pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale END");
-
- return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0;
-}
-
-static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
- unsigned int detail,
- char *buf,unsigned int maxlen)
-{
- unsigned int ccnt,bcnt;
- int spcfl = 0;
- const struct pvr2_i2c_op *opf;
-
- ccnt = 0;
- if (detail & PVR2_I2C_DETAIL_DEBUG) {
- bcnt = scnprintf(buf,maxlen,
- "ctxt=%p ctl_mask=0x%lx",
- cp,cp->ctl_mask);
- ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
- spcfl = !0;
- }
- bcnt = scnprintf(buf,maxlen,
- "%s%s @ 0x%x",
- (spcfl ? " " : ""),
- cp->client->name,
- cp->client->addr);
- ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
- if ((detail & PVR2_I2C_DETAIL_HANDLER) &&
- cp->handler && cp->handler->func_table->describe) {
- bcnt = scnprintf(buf,maxlen," (");
- ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
- bcnt = cp->handler->func_table->describe(
- cp->handler->func_data,buf,maxlen);
- ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
- bcnt = scnprintf(buf,maxlen,")");
- ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
- }
- if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) {
- unsigned int idx;
- unsigned long msk,sm;
-
- bcnt = scnprintf(buf,maxlen," [");
- ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
- sm = 0;
- spcfl = 0;
- for (idx = 0, msk = 1; msk; idx++, msk <<= 1) {
- if (!(cp->ctl_mask & msk)) continue;
- opf = pvr2_i2c_get_op(idx);
- if (opf) {
- bcnt = scnprintf(buf,maxlen,"%s%s",
- spcfl ? " " : "",
- opf->name);
- ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
- spcfl = !0;
- } else {
- sm |= msk;
- }
- }
- if (sm) {
- bcnt = scnprintf(buf,maxlen,"%s%lx",
- idx != 0 ? " " : "",sm);
- ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
- }
- bcnt = scnprintf(buf,maxlen,"]");
- ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
- }
- return ccnt;
-}
-
-unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw,
- char *buf,unsigned int maxlen)
-{
- unsigned int ccnt,bcnt;
- struct pvr2_i2c_client *cp;
- ccnt = 0;
- mutex_lock(&hdw->i2c_list_lock); do {
- list_for_each_entry(cp, &hdw->i2c_clients, list) {
- bcnt = pvr2_i2c_client_describe(
- cp,
- (PVR2_I2C_DETAIL_HANDLER|
- PVR2_I2C_DETAIL_CTLMASK),
- buf,maxlen);
- ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
- bcnt = scnprintf(buf,maxlen,"\n");
- ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
- }
- } while (0); mutex_unlock(&hdw->i2c_list_lock);
- return ccnt;
-}
-
static int pvr2_i2c_attach_inform(struct i2c_client *client)
{
- struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
- struct pvr2_i2c_client *cp;
- int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL);
- cp = kzalloc(sizeof(*cp),GFP_KERNEL);
- trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]",
- client->name,
- client->addr,cp);
- if (!cp) return -ENOMEM;
- cp->hdw = hdw;
- INIT_LIST_HEAD(&cp->list);
- cp->client = client;
- mutex_lock(&hdw->i2c_list_lock); do {
- hdw->cropcap_stale = !0;
- list_add_tail(&cp->list,&hdw->i2c_clients);
- hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT;
- } while (0); mutex_unlock(&hdw->i2c_list_lock);
- if (fl) queue_work(hdw->workqueue,&hdw->worki2csync);
return 0;
}
static int pvr2_i2c_detach_inform(struct i2c_client *client)
{
- struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
- struct pvr2_i2c_client *cp, *ncp;
- unsigned long amask = 0;
- int foundfl = 0;
- mutex_lock(&hdw->i2c_list_lock); do {
- hdw->cropcap_stale = !0;
- list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
- if (cp->client == client) {
- trace_i2c("pvr2_i2c_detach"
- " [client=%s @ 0x%x ctxt=%p]",
- client->name,
- client->addr,cp);
- if (cp->handler &&
- cp->handler->func_table->detach) {
- cp->handler->func_table->detach(
- cp->handler->func_data);
- }
- list_del(&cp->list);
- kfree(cp);
- foundfl = !0;
- continue;
- }
- amask |= cp->ctl_mask;
- }
- hdw->i2c_active_mask = amask;
- } while (0); mutex_unlock(&hdw->i2c_list_lock);
- if (!foundfl) {
- trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=<unknown>]",
- client->name,
- client->addr);
- }
return 0;
}
@@ -1020,7 +615,7 @@ static struct i2c_algorithm pvr2_i2c_algo_template = {
static struct i2c_adapter pvr2_i2c_adap_template = {
.owner = THIS_MODULE,
- .class = I2C_CLASS_TV_ANALOG,
+ .class = 0,
.id = I2C_HW_B_BT848,
.client_register = pvr2_i2c_attach_inform,
.client_unregister = pvr2_i2c_detach_inform,
@@ -1087,12 +682,8 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev;
hdw->i2c_adap.algo = &hdw->i2c_algo;
hdw->i2c_adap.algo_data = hdw;
- hdw->i2c_pend_mask = 0;
- hdw->i2c_stale_mask = 0;
- hdw->i2c_active_mask = 0;
- INIT_LIST_HEAD(&hdw->i2c_clients);
- mutex_init(&hdw->i2c_list_lock);
hdw->i2c_linked = !0;
+ i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev);
i2c_add_adapter(&hdw->i2c_adap);
if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
/* Probe for a different type of IR receiver on this
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
index 6ef7a1c0e..6a7576920 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
@@ -20,68 +20,13 @@
#ifndef __PVRUSB2_I2C_CORE_H
#define __PVRUSB2_I2C_CORE_H
-#include <linux/list.h>
-#include <linux/i2c.h>
-
struct pvr2_hdw;
-struct pvr2_i2c_client;
-struct pvr2_i2c_handler;
-struct pvr2_i2c_handler_functions;
-struct pvr2_i2c_op;
-struct pvr2_i2c_op_functions;
-
-struct pvr2_i2c_client {
- struct i2c_client *client;
- struct pvr2_i2c_handler *handler;
- struct list_head list;
- struct pvr2_hdw *hdw;
- int detected_flag;
- int recv_enable;
- unsigned long pend_mask;
- unsigned long ctl_mask;
- void (*status_poll)(struct pvr2_i2c_client *);
-};
-
-struct pvr2_i2c_handler {
- void *func_data;
- const struct pvr2_i2c_handler_functions *func_table;
-};
-
-struct pvr2_i2c_handler_functions {
- void (*detach)(void *);
- int (*check)(void *);
- void (*update)(void *);
- unsigned int (*describe)(void *,char *,unsigned int);
-};
-
-struct pvr2_i2c_op {
- int (*check)(struct pvr2_hdw *);
- void (*update)(struct pvr2_hdw *);
- const char *name;
-};
void pvr2_i2c_core_init(struct pvr2_hdw *);
void pvr2_i2c_core_done(struct pvr2_hdw *);
-int pvr2_i2c_client_cmd(struct pvr2_i2c_client *,unsigned int cmd,void *arg);
-int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg);
-
-int pvr2_i2c_core_check_stale(struct pvr2_hdw *);
-void pvr2_i2c_core_sync(struct pvr2_hdw *);
-void pvr2_i2c_core_status_poll(struct pvr2_hdw *);
-unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen);
-#define PVR2_I2C_DETAIL_DEBUG 0x0001
-#define PVR2_I2C_DETAIL_HANDLER 0x0002
-#define PVR2_I2C_DETAIL_CTLMASK 0x0004
-#define PVR2_I2C_DETAIL_ALL (\
- PVR2_I2C_DETAIL_DEBUG |\
- PVR2_I2C_DETAIL_HANDLER |\
- PVR2_I2C_DETAIL_CTLMASK)
-
-void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *);
-const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx);
-#endif /* __PVRUSB2_I2C_CORE_H */
+#endif /* __PVRUSB2_I2C_ADAPTER_H */
/*
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c
deleted file mode 100644
index efec78516..000000000
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- *
- *
- * Copyright (C) 2005 Mike Isely <isely@pobox.com>
- * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- * 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
- *
- * 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 "pvrusb2.h"
-#include "pvrusb2-util.h"
-#include "pvrusb2-tuner.h"
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include "compat.h"
-#include <linux/videodev2.h>
-#include <media/tuner.h>
-#include <media/v4l2-common.h>
-
-struct pvr2_tuner_handler {
- struct pvr2_hdw *hdw;
- struct pvr2_i2c_client *client;
- struct pvr2_i2c_handler i2c_handler;
- int type_update_fl;
-};
-
-
-static void set_type(struct pvr2_tuner_handler *ctxt)
-{
- struct pvr2_hdw *hdw = ctxt->hdw;
- struct tuner_setup setup;
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c tuner set_type(%d)",hdw->tuner_type);
- if (((int)(hdw->tuner_type)) < 0) return;
-
- setup.addr = ADDR_UNSET;
- setup.type = hdw->tuner_type;
- setup.mode_mask = T_RADIO | T_ANALOG_TV;
- /* We may really want mode_mask to be T_ANALOG_TV for now */
- pvr2_i2c_client_cmd(ctxt->client,TUNER_SET_TYPE_ADDR,&setup);
- ctxt->type_update_fl = 0;
-}
-
-
-static int tuner_check(struct pvr2_tuner_handler *ctxt)
-{
- struct pvr2_hdw *hdw = ctxt->hdw;
- if (hdw->tuner_updated) ctxt->type_update_fl = !0;
- return ctxt->type_update_fl != 0;
-}
-
-
-static void tuner_update(struct pvr2_tuner_handler *ctxt)
-{
- if (ctxt->type_update_fl) set_type(ctxt);
-}
-
-
-static void pvr2_tuner_detach(struct pvr2_tuner_handler *ctxt)
-{
- ctxt->client->handler = NULL;
- kfree(ctxt);
-}
-
-
-static unsigned int pvr2_tuner_describe(struct pvr2_tuner_handler *ctxt,char *buf,unsigned int cnt)
-{
- return scnprintf(buf,cnt,"handler: pvrusb2-tuner");
-}
-
-
-static const struct pvr2_i2c_handler_functions tuner_funcs = {
- .detach = (void (*)(void *))pvr2_tuner_detach,
- .check = (int (*)(void *))tuner_check,
- .update = (void (*)(void *))tuner_update,
- .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_tuner_describe,
-};
-
-
-int pvr2_i2c_tuner_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
-{
- struct pvr2_tuner_handler *ctxt;
- if (cp->handler) return 0;
-
- ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
- if (!ctxt) return 0;
-
- ctxt->i2c_handler.func_data = ctxt;
- ctxt->i2c_handler.func_table = &tuner_funcs;
- ctxt->type_update_fl = !0;
- ctxt->client = cp;
- ctxt->hdw = hdw;
- cp->handler = &ctxt->i2c_handler;
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x tuner handler set up",
- cp->client->addr);
- return !0;
-}
-
-
-
-
-/*
- Stuff for Emacs to see, in order to encourage consistent editing style:
- *** Local Variables: ***
- *** mode: c ***
- *** fill-column: 70 ***
- *** tab-width: 8 ***
- *** c-basic-offset: 8 ***
- *** End: ***
- */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index e4bf0278c..c7fc605f8 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -953,10 +953,6 @@ static long pvr2_v4l2_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
-/* Temporary hack : use ivtv api until a v4l2 one is available. */
-#define IVTV_IOC_G_CODEC 0xFFEE7703
-#define IVTV_IOC_S_CODEC 0xFFEE7704
- if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
return video_usercopy(file, cmd, arg, pvr2_v4l2_do_ioctl);
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
index b1ff3803f..b29a42ef5 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
@@ -28,7 +28,7 @@
*/
#include "pvrusb2-video-v4l.h"
-#include "pvrusb2-i2c-cmd-v4l2.h"
+
#include "pvrusb2-hdw-internal.h"
@@ -40,15 +40,6 @@
#include <linux/slab.h>
#include "compat.h"
-struct pvr2_v4l_decoder {
- struct pvr2_i2c_handler handler;
- struct pvr2_decoder_ctrl ctrl;
- struct pvr2_i2c_client *client;
- struct pvr2_hdw *hdw;
- unsigned long stale_mask;
-};
-
-
struct routing_scheme {
const int *def;
unsigned int cnt;
@@ -64,190 +55,51 @@ static const int routing_scheme0[] = {
[PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2,
};
+static const int routing_scheme1[] = {
+ [PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4,
+ [PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5,
+ [PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE3,
+ [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, /* or SVIDEO0, it seems */
+};
+
static const struct routing_scheme routing_schemes[] = {
[PVR2_ROUTING_SCHEME_HAUPPAUGE] = {
.def = routing_scheme0,
.cnt = ARRAY_SIZE(routing_scheme0),
},
+ [PVR2_ROUTING_SCHEME_ONAIR] = {
+ .def = routing_scheme1,
+ .cnt = ARRAY_SIZE(routing_scheme1),
+ },
};
-static void set_input(struct pvr2_v4l_decoder *ctxt)
-{
- struct pvr2_hdw *hdw = ctxt->hdw;
- struct v4l2_routing route;
- const struct routing_scheme *sp;
- unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
-
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)",hdw->input_val);
-
- if ((sid < ARRAY_SIZE(routing_schemes)) &&
- ((sp = routing_schemes + sid) != NULL) &&
- (hdw->input_val >= 0) &&
- (hdw->input_val < sp->cnt)) {
- route.input = sp->def[hdw->input_val];
- } else {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "*** WARNING *** i2c v4l2 set_input:"
- " Invalid routing scheme (%u) and/or input (%d)",
- sid,hdw->input_val);
- return;
- }
-
- route.output = 0;
- pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route);
-}
-
-
-static int check_input(struct pvr2_v4l_decoder *ctxt)
-{
- struct pvr2_hdw *hdw = ctxt->hdw;
- return hdw->input_dirty != 0;
-}
-
-
-static void set_audio(struct pvr2_v4l_decoder *ctxt)
-{
- u32 val;
- struct pvr2_hdw *hdw = ctxt->hdw;
-
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_audio %d",
- hdw->srate_val);
- switch (hdw->srate_val) {
- default:
- case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
- val = 48000;
- break;
- case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
- val = 44100;
- break;
- case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
- val = 32000;
- break;
- }
- pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val);
-}
-
-
-static int check_audio(struct pvr2_v4l_decoder *ctxt)
-{
- struct pvr2_hdw *hdw = ctxt->hdw;
- return hdw->srate_dirty != 0;
-}
-
-
-struct pvr2_v4l_decoder_ops {
- void (*update)(struct pvr2_v4l_decoder *);
- int (*check)(struct pvr2_v4l_decoder *);
-};
-
-
-static const struct pvr2_v4l_decoder_ops decoder_ops[] = {
- { .update = set_input, .check = check_input},
- { .update = set_audio, .check = check_audio},
-};
-
-
-static void decoder_detach(struct pvr2_v4l_decoder *ctxt)
+void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
{
- ctxt->client->handler = NULL;
- pvr2_hdw_set_decoder(ctxt->hdw,NULL);
- kfree(ctxt);
-}
-
-
-static int decoder_check(struct pvr2_v4l_decoder *ctxt)
-{
- unsigned long msk;
- unsigned int idx;
-
- for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
- msk = 1 << idx;
- if (ctxt->stale_mask & msk) continue;
- if (decoder_ops[idx].check(ctxt)) {
- ctxt->stale_mask |= msk;
+ if (hdw->input_dirty || hdw->force_dirty) {
+ struct v4l2_routing route;
+ const struct routing_scheme *sp;
+ unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)",
+ hdw->input_val);
+ if ((sid < ARRAY_SIZE(routing_schemes)) &&
+ ((sp = routing_schemes + sid) != NULL) &&
+ (hdw->input_val >= 0) &&
+ (hdw->input_val < sp->cnt)) {
+ route.input = sp->def[hdw->input_val];
+ } else {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "*** WARNING *** subdev v4l2 set_input:"
+ " Invalid routing scheme (%u)"
+ " and/or input (%d)",
+ sid, hdw->input_val);
+ return;
}
+ route.output = 0;
+ sd->ops->video->s_routing(sd, &route);
}
- return ctxt->stale_mask != 0;
-}
-
-
-static void decoder_update(struct pvr2_v4l_decoder *ctxt)
-{
- unsigned long msk;
- unsigned int idx;
-
- for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
- msk = 1 << idx;
- if (!(ctxt->stale_mask & msk)) continue;
- ctxt->stale_mask &= ~msk;
- decoder_ops[idx].update(ctxt);
- }
-}
-
-
-static int decoder_detect(struct pvr2_i2c_client *cp)
-{
- /* Attempt to query the decoder - let's see if it will answer */
- struct v4l2_tuner vt;
- int ret;
-
- memset(&vt,0,sizeof(vt));
- ret = pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&vt);
- return ret == 0; /* Return true if it answered */
-}
-
-
-static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl)
-{
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 decoder_enable(%d)",fl);
- pvr2_v4l2_cmd_stream(ctxt->client,fl);
-}
-
-
-static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt)
-{
- return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l");
-}
-
-
-static const struct pvr2_i2c_handler_functions hfuncs = {
- .detach = (void (*)(void *))decoder_detach,
- .check = (int (*)(void *))decoder_check,
- .update = (void (*)(void *))decoder_update,
- .describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe,
-};
-
-
-int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw,
- struct pvr2_i2c_client *cp)
-{
- struct pvr2_v4l_decoder *ctxt;
-
- if (hdw->decoder_ctrl) return 0;
- if (cp->handler) return 0;
- if (!decoder_detect(cp)) return 0;
-
- ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
- if (!ctxt) return 0;
-
- ctxt->handler.func_data = ctxt;
- ctxt->handler.func_table = &hfuncs;
- ctxt->ctrl.ctxt = ctxt;
- ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
- ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
- ctxt->client = cp;
- ctxt->hdw = hdw;
- ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1;
- pvr2_hdw_set_decoder(hdw,&ctxt->ctrl);
- cp->handler = &ctxt->handler;
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x saa711x V4L2 handler set up",
- cp->client->addr);
- return !0;
}
-
-
/*
Stuff for Emacs to see, in order to encourage consistent editing style:
*** Local Variables: ***
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
index 4ff5b892b..3b0bd5db6 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
@@ -32,11 +32,8 @@
*/
-
-#include "pvrusb2-i2c-core.h"
-
-int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
-
+#include "pvrusb2-hdw-internal.h"
+void pvr2_saa7115_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *);
#endif /* __PVRUSB2_VIDEO_V4L_H */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
index 6cdcbf2fe..6364434a5 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
@@ -27,7 +27,6 @@
*/
#include "pvrusb2-wm8775.h"
-#include "pvrusb2-i2c-cmd-v4l2.h"
#include "pvrusb2-hdw-internal.h"
@@ -38,128 +37,31 @@
#include <linux/slab.h>
#include "compat.h"
-struct pvr2_v4l_wm8775 {
- struct pvr2_i2c_handler handler;
- struct pvr2_i2c_client *client;
- struct pvr2_hdw *hdw;
- unsigned long stale_mask;
-};
-
-
-static void set_input(struct pvr2_v4l_wm8775 *ctxt)
-{
- struct v4l2_routing route;
- struct pvr2_hdw *hdw = ctxt->hdw;
-
- memset(&route,0,sizeof(route));
-
- switch(hdw->input_val) {
- case PVR2_CVAL_INPUT_RADIO:
- route.input = 1;
- break;
- default:
- /* All other cases just use the second input */
- route.input = 2;
- break;
- }
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d route=0x%x)",
- hdw->input_val,route.input);
-
- pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
-}
-
-static int check_input(struct pvr2_v4l_wm8775 *ctxt)
-{
- struct pvr2_hdw *hdw = ctxt->hdw;
- return hdw->input_dirty != 0;
-}
-
-
-struct pvr2_v4l_wm8775_ops {
- void (*update)(struct pvr2_v4l_wm8775 *);
- int (*check)(struct pvr2_v4l_wm8775 *);
-};
-
-
-static const struct pvr2_v4l_wm8775_ops wm8775_ops[] = {
- { .update = set_input, .check = check_input},
-};
-
-
-static unsigned int wm8775_describe(struct pvr2_v4l_wm8775 *ctxt,
- char *buf,unsigned int cnt)
-{
- return scnprintf(buf,cnt,"handler: pvrusb2-wm8775");
-}
-
-
-static void wm8775_detach(struct pvr2_v4l_wm8775 *ctxt)
+void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
{
- ctxt->client->handler = NULL;
- kfree(ctxt);
-}
-
-
-static int wm8775_check(struct pvr2_v4l_wm8775 *ctxt)
-{
- unsigned long msk;
- unsigned int idx;
-
- for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) {
- msk = 1 << idx;
- if (ctxt->stale_mask & msk) continue;
- if (wm8775_ops[idx].check(ctxt)) {
- ctxt->stale_mask |= msk;
+ if (hdw->input_dirty || hdw->force_dirty) {
+ struct v4l2_routing route;
+
+ memset(&route, 0, sizeof(route));
+
+ switch (hdw->input_val) {
+ case PVR2_CVAL_INPUT_RADIO:
+ route.input = 1;
+ break;
+ default:
+ /* All other cases just use the second input */
+ route.input = 2;
+ break;
}
- }
- return ctxt->stale_mask != 0;
-}
-
-
-static void wm8775_update(struct pvr2_v4l_wm8775 *ctxt)
-{
- unsigned long msk;
- unsigned int idx;
+ pvr2_trace(PVR2_TRACE_CHIPS, "subdev wm8775"
+ " set_input(val=%d route=0x%x)",
+ hdw->input_val, route.input);
- for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) {
- msk = 1 << idx;
- if (!(ctxt->stale_mask & msk)) continue;
- ctxt->stale_mask &= ~msk;
- wm8775_ops[idx].update(ctxt);
+ sd->ops->audio->s_routing(sd, &route);
}
}
-static const struct pvr2_i2c_handler_functions hfuncs = {
- .detach = (void (*)(void *))wm8775_detach,
- .check = (int (*)(void *))wm8775_check,
- .update = (void (*)(void *))wm8775_update,
- .describe = (unsigned int (*)(void *,char *,unsigned int))wm8775_describe,
-};
-
-
-int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
-{
- struct pvr2_v4l_wm8775 *ctxt;
-
- if (cp->handler) return 0;
-
- ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
- if (!ctxt) return 0;
-
- ctxt->handler.func_data = ctxt;
- ctxt->handler.func_table = &hfuncs;
- ctxt->client = cp;
- ctxt->hdw = hdw;
- ctxt->stale_mask = (1 << ARRAY_SIZE(wm8775_ops)) - 1;
- cp->handler = &ctxt->handler;
- pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x wm8775 V4L2 handler set up",
- cp->client->addr);
- return !0;
-}
-
-
-
/*
Stuff for Emacs to see, in order to encourage consistent editing style:
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
index 807090961..0577bc724 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
@@ -34,9 +34,9 @@
-#include "pvrusb2-i2c-core.h"
+#include "pvrusb2-hdw-internal.h"
-int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+void pvr2_wm8775_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd);
#endif /* __PVRUSB2_WM8775_H */