V4L/DVB (4228a): pvrusb2 to kernel 2.6.18

Implement V4L2 driver for the Hauppauge PVR USB2 TV tuner.

The Hauppauge PVR USB2 is a USB connected TV tuner with an embedded
cx23416 hardware MPEG2 encoder.  There are two major variants of this
device; this driver handles both.  Any V4L2 application which
understands MPEG2 video stream data should be able to work with this
device.

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
new file mode 100644
index 0000000..217bbe5
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -0,0 +1,371 @@
+/*
+ *
+ *  $Id$
+ *
+ *  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
+ *
+ */
+#ifndef __PVRUSB2_HDW_INTERNAL_H
+#define __PVRUSB2_HDW_INTERNAL_H
+
+/*
+
+  This header sets up all the internal structures and definitions needed to
+  track and coordinate the driver's interaction with the hardware.  ONLY
+  source files which actually implement part of that whole circus should be
+  including this header.  Higher levels, like the external layers to the
+  various public APIs (V4L, sysfs, etc) should NOT ever include this
+  private, internal header.  This means that pvrusb2-hdw, pvrusb2-encoder,
+  etc will include this, but pvrusb2-v4l should not.
+
+*/
+
+#include <linux/config.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-io.h"
+
+/* Legal values for the SRATE state variable */
+#define PVR2_CVAL_SRATE_48 0
+#define PVR2_CVAL_SRATE_44_1 1
+
+/* Legal values for the AUDIOBITRATE state variable */
+#define PVR2_CVAL_AUDIOBITRATE_384 0
+#define PVR2_CVAL_AUDIOBITRATE_320 1
+#define PVR2_CVAL_AUDIOBITRATE_256 2
+#define PVR2_CVAL_AUDIOBITRATE_224 3
+#define PVR2_CVAL_AUDIOBITRATE_192 4
+#define PVR2_CVAL_AUDIOBITRATE_160 5
+#define PVR2_CVAL_AUDIOBITRATE_128 6
+#define PVR2_CVAL_AUDIOBITRATE_112 7
+#define PVR2_CVAL_AUDIOBITRATE_96 8
+#define PVR2_CVAL_AUDIOBITRATE_80 9
+#define PVR2_CVAL_AUDIOBITRATE_64 10
+#define PVR2_CVAL_AUDIOBITRATE_56 11
+#define PVR2_CVAL_AUDIOBITRATE_48 12
+#define PVR2_CVAL_AUDIOBITRATE_32 13
+#define PVR2_CVAL_AUDIOBITRATE_VBR 14
+
+/* Legal values for the AUDIOEMPHASIS state variable */
+#define PVR2_CVAL_AUDIOEMPHASIS_NONE 0
+#define PVR2_CVAL_AUDIOEMPHASIS_50_15 1
+#define PVR2_CVAL_AUDIOEMPHASIS_CCITT 2
+
+/* Legal values for PVR2_CID_HSM */
+#define PVR2_CVAL_HSM_FAIL 0
+#define PVR2_CVAL_HSM_FULL 1
+#define PVR2_CVAL_HSM_HIGH 2
+
+#define PVR2_VID_ENDPOINT        0x84
+#define PVR2_UNK_ENDPOINT        0x86    /* maybe raw yuv ? */
+#define PVR2_VBI_ENDPOINT        0x88
+
+#define PVR2_CTL_BUFFSIZE        64
+
+#define FREQTABLE_SIZE 500
+
+#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_get_value)(struct pvr2_ctrl *,int *);
+typedef int (*pvr2_ctlf_set_value)(struct pvr2_ctrl *,int msk,int val);
+typedef int (*pvr2_ctlf_val_to_sym)(struct pvr2_ctrl *,int msk,int val,
+				    char *,unsigned int,unsigned int *);
+typedef int (*pvr2_ctlf_sym_to_val)(struct pvr2_ctrl *,
+				    const char *,unsigned int,
+				    int *mskp,int *valp);
+
+/* This structure describes a specific control.  A table of these is set up
+   in pvrusb2-hdw.c. */
+struct pvr2_ctl_info {
+	/* Control's name suitable for use as an identifier */
+	const char *name;
+
+	/* Short description of control */
+	const char *desc;
+
+	/* Control's implementation */
+	pvr2_ctlf_get_value get_value;      /* Get its value */
+	pvr2_ctlf_set_value set_value;      /* Set its value */
+	pvr2_ctlf_val_to_sym val_to_sym;    /* Custom convert value->symbol */
+	pvr2_ctlf_sym_to_val sym_to_val;    /* Custom convert symbol->value */
+	pvr2_ctlf_is_dirty is_dirty;        /* Return true if dirty */
+	pvr2_ctlf_clear_dirty clear_dirty;  /* Clear dirty state */
+
+	/* Control's type (int, enum, bitmask) */
+	enum pvr2_ctl_type type;
+
+	/* Associated V4L control ID, if any */
+	int v4l_id;
+
+	/* Associated driver internal ID, if any */
+	int internal_id;
+
+	/* Don't implicitly initialize this control's value */
+	int skip_init;
+
+	/* Starting value for this control */
+	int default_value;
+
+	/* Type-specific control information */
+	union {
+		struct { /* Integer control */
+			long min_value; /* lower limit */
+			long max_value; /* upper limit */
+		} type_int;
+		struct { /* enumerated control */
+			unsigned int count;       /* enum value count */
+			const char **value_names; /* symbol names */
+		} type_enum;
+		struct { /* bitmask control */
+			unsigned int valid_bits; /* bits in use */
+			const char **bit_names;  /* symbol name/bit */
+		} type_bitmask;
+	} def;
+};
+
+
+struct pvr2_ctrl {
+	const struct pvr2_ctl_info *info;
+	struct pvr2_hdw *hdw;
+};
+
+
+struct pvr2_audio_stat {
+	void *ctxt;
+	void (*detach)(void *);
+	int (*status)(void *);
+};
+
+struct pvr2_decoder_ctrl {
+	void *ctxt;
+	void (*detach)(void *);
+	void (*enable)(void *,int);
+	int (*tuned)(void *);
+	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
+#define FW1_STATE_MISSING 1
+#define FW1_STATE_FAILED 2
+#define FW1_STATE_RELOAD 3
+#define FW1_STATE_OK 4
+
+/* Known major hardware variants, keyed from device ID */
+#define PVR2_HDW_TYPE_29XXX 0
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+#define PVR2_HDW_TYPE_24XXX 1
+#endif
+
+typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
+#define PVR2_I2C_FUNC_CNT 128
+
+/* This structure contains all state data directly needed to
+   manipulate the hardware (as opposed to complying with a kernel
+   interface) */
+struct pvr2_hdw {
+	/* Underlying USB device handle */
+	struct usb_device *usb_dev;
+	struct usb_interface *usb_intf;
+
+	/* Device type, one of PVR2_HDW_TYPE_xxxxx */
+	unsigned int hdw_type;
+
+	/* Video spigot */
+	struct pvr2_stream *vid_stream;
+
+	/* Mutex for all hardware state control */
+	struct mutex big_lock_mutex;
+	int big_lock_held;  /* For debugging */
+
+	void (*poll_trigger_func)(void *);
+	void *poll_trigger_data;
+
+	char name[32];
+
+	/* I2C stuff */
+	struct i2c_adapter i2c_adap;
+	struct i2c_algorithm i2c_algo;
+	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];
+	unsigned int freqProgSlot;
+	unsigned int freqSlot;
+
+	/* Stuff for handling low level control interaction with device */
+	struct mutex ctl_lock_mutex;
+	int ctl_lock_held;  /* For debugging */
+	struct urb *ctl_write_urb;
+	struct urb *ctl_read_urb;
+	unsigned char *ctl_write_buffer;
+	unsigned char *ctl_read_buffer;
+	volatile int ctl_write_pend_flag;
+	volatile int ctl_read_pend_flag;
+	volatile int ctl_timeout_flag;
+	struct completion ctl_done;
+	unsigned char cmd_buffer[PVR2_CTL_BUFFSIZE];
+	int cmd_debug_state;               // Low level command debugging info
+	unsigned char cmd_debug_code;      //
+	unsigned int cmd_debug_write_len;  //
+	unsigned int cmd_debug_read_len;   //
+
+	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
+	int flag_streaming_enabled; // true if streaming should be on
+	int fw1_state;          // current situation with fw1
+
+	int flag_decoder_is_tuned;
+
+	struct pvr2_decoder_ctrl *decoder_ctrl;
+
+	// CPU firmware info (used to help find / save firmware data)
+	char *fw_buffer;
+	unsigned int fw_size;
+
+	// Which subsystem pieces have been enabled / configured
+	unsigned long subsys_enabled_mask;
+
+	// Which subsystems are manipulated to enable streaming
+	unsigned long subsys_stream_mask;
+
+	// 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;
+	unsigned int freqVal;
+	int freqDirty;
+
+	/* Video standard handling */
+	v4l2_std_id std_mask_eeprom; // Hardware supported selections
+	v4l2_std_id std_mask_avail;  // Which standards we may select from
+	v4l2_std_id std_mask_cur;    // Currently selected standard(s)
+	unsigned int std_enum_cnt;   // # of enumerated standards
+	int std_enum_cur;            // selected standard enumeration value
+	int std_dirty;               // True if std_mask_cur has changed
+	struct pvr2_ctl_info std_info_enum;
+	struct pvr2_ctl_info std_info_avail;
+	struct pvr2_ctl_info std_info_cur;
+	struct v4l2_standard *std_defs;
+	const char **std_enum_names;
+
+	// Generated string names, one per actual V4L2 standard
+	const char *std_mask_ptrs[32];
+	char std_mask_names[32][10];
+
+	int unit_number;             /* ID for driver instance */
+	unsigned long serial_number; /* ID for hardware itself */
+
+	/* Minor number used by v4l logic (yes, this is a hack, as there should
+	   be no v4l junk here).  Probably a better way to do this. */
+	int v4l_minor_number;
+
+	/* Location of eeprom or a negative number if none */
+	int eeprom_addr;
+
+	enum pvr2_config config;
+
+	/* Information about what audio signal we're hearing */
+	int flag_stereo;
+	int flag_bilingual;
+	struct pvr2_audio_stat *audio_stat;
+
+	/* Control state */
+#define VCREATE_DATA(lab) int lab##_val; int lab##_dirty
+	VCREATE_DATA(brightness);
+	VCREATE_DATA(contrast);
+	VCREATE_DATA(saturation);
+	VCREATE_DATA(hue);
+	VCREATE_DATA(volume);
+	VCREATE_DATA(balance);
+	VCREATE_DATA(bass);
+	VCREATE_DATA(treble);
+	VCREATE_DATA(mute);
+	VCREATE_DATA(srate);
+	VCREATE_DATA(audiobitrate);
+	VCREATE_DATA(audiocrc);
+	VCREATE_DATA(audioemphasis);
+	VCREATE_DATA(vbr);
+	VCREATE_DATA(videobitrate);
+	VCREATE_DATA(videopeak);
+	VCREATE_DATA(input);
+	VCREATE_DATA(audiomode);
+	VCREATE_DATA(res_hor);
+	VCREATE_DATA(res_ver);
+	VCREATE_DATA(interlace);
+	VCREATE_DATA(audiolayer);
+#undef VCREATE_DATA
+
+	struct pvr2_ctrl *controls;
+};
+
+int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw);
+
+unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *);
+
+void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
+				     unsigned long msk,unsigned long val);
+void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw,
+					    unsigned long msk,
+					    unsigned long val);
+
+void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
+void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
+
+int pvr2_i2c_basic_op(struct pvr2_hdw *,u8 i2c_addr,
+		      u8 *wdata,u16 wlen,
+		      u8 *rdata,u16 rlen);
+
+#endif /* __PVRUSB2_HDW_INTERNAL_H */
+
+/*
+  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: ***
+  */