diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-04-02 03:24:11 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-04-02 03:24:11 -0300 |
commit | e1fbc574390b85339c21945ec238e87018601a08 (patch) | |
tree | f867f3c77fdd72133e0b5295475e71804039cffe /linux/drivers/media | |
parent | dbe2e81959f002660345a0b09161b230df7765cf (diff) | |
parent | b2dfa0b965563e6fdc3bb36dde59473b97b01a6a (diff) | |
download | mediapointer-dvb-s2-e1fbc574390b85339c21945ec238e87018601a08.tar.gz mediapointer-dvb-s2-e1fbc574390b85339c21945ec238e87018601a08.tar.bz2 |
Merge from http://linuxtv.org/hg/~hverkuil/v4l-dvb
From: Mauro Carvalho Chehab <mchehab@infradead.org>
merge:
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'linux/drivers/media')
-rw-r--r-- | linux/drivers/media/video/cx88/Kconfig | 13 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/Kconfig | 45 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/Makefile | 13 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-audio.c | 23 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c | 116 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.h | 1 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c | 12 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 125 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1006 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h | 200 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | 4 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 30 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 15 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-main.c | 10 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 134 | ||||
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 400 |
16 files changed, 1307 insertions, 840 deletions
diff --git a/linux/drivers/media/video/cx88/Kconfig b/linux/drivers/media/video/cx88/Kconfig index 2c586f903..630273992 100644 --- a/linux/drivers/media/video/cx88/Kconfig +++ b/linux/drivers/media/video/cx88/Kconfig @@ -1,3 +1,7 @@ +config VIDEO_CX88_VP3054 + tristate + depends on VIDEO_CX88_DVB && DVB_MT352 + config VIDEO_CX88 tristate "Conexant 2388x (bt878 successor) support" depends on VIDEO_DEV && PCI && I2C @@ -73,10 +77,11 @@ config VIDEO_CX88_DVB_MT352 This adds DVB-T support for cards based on the Connexant 2388x chip and the MT352 demodulator. -config VIDEO_CX88_VP3054 - tristate "VP-3054 Secondary I2C Bus Support" - default m - depends on DVB_MT352 +config VIDEO_CX88_DVB_VP3054 + bool "VP-3054 Secondary I2C Bus Support" + default y + depends on VIDEO_CX88_DVB_MT352 + select VIDEO_CX88_VP3054 ---help--- This adds DVB-T support for cards based on the Connexant 2388x chip and the MT352 demodulator, diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 9824ad267..629dc4e05 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -12,3 +12,48 @@ config VIDEO_PVRUSB2 To compile this driver as a module, choose M here: the module will be called pvrusb2 + +config VIDEO_PVRUSB2_24XXX + bool "Hauppauge WinTV-PVR USB2 support for 24xxx model series" + depends on VIDEO_PVRUSB2 && EXPERIMENTAL + ---help--- + This option enables inclusion of additional logic to operate + newer WinTV-PVR USB2 devices whose model number is of the + form "24xxx" (leading prefix of "24" followed by 3 digits). + To see if you may need this option, examine the white + sticker on the underside of your device. Enabling this + option will not harm support for older devices, however it + is a separate option because of the experimental nature of + this new feature. + + If you are in doubt, say N. + + Note: This feature is _very_ experimental. You have been + warned. + +config VIDEO_PVRUSB2_SYSFS + bool "pvrusb2 sysfs support" + default y + depends on VIDEO_PVRUSB2 && SYSFS && EXPERIMENTAL + ---help--- + This option enables the operation of a sysfs based + interface for query and control of the pvrusb2 driver. + + This is not generally needed for v4l applications, + although certain applications are optimized to take + advantage of this feature. + + If you are in doubt, say Y. + + Note: This feature is experimental and subject to change. + +config VIDEO_PVRUSB2_DEBUGIFC + bool "pvrusb2 debug interface" + depends on VIDEO_PVRUSB2_SYSFS + ---help--- + This option enables the inclusion of a debug interface + in the pvrusb2 driver, hosted through sysfs. + + You do not need to select this option unless you plan + on debugging the driver or performing a manual firmware + extraction. diff --git a/linux/drivers/media/video/pvrusb2/Makefile b/linux/drivers/media/video/pvrusb2/Makefile index 4a37fe723..53fccce4f 100644 --- a/linux/drivers/media/video/pvrusb2/Makefile +++ b/linux/drivers/media/video/pvrusb2/Makefile @@ -1,11 +1,18 @@ +obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o +obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o + +obj-pvrusb2-24xxx-$(CONFIG_VIDEO_PVRUSB2_24XXX) := \ + pvrusb2-cx2584x-v4l.o \ + pvrusb2-wm8775.o + pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \ pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \ pvrusb2-encoder.o pvrusb2-video-v4l.o \ pvrusb2-eeprom.o pvrusb2-tuner.o pvrusb2-demod.o \ pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \ - pvrusb2-sysfs.o pvrusb2-context.o pvrusb2-io.o \ - pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \ - pvrusb2-ioread.o pvrusb2-debugifc.o + pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \ + $(obj-pvrusb2-24xxx-y) \ + $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y) obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c index 031412327..7f29a8821 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -37,26 +37,6 @@ struct pvr2_msp3400_handler { }; -static int xlat_audiomode_to_v4l2(int id) -{ - switch (id) { - case PVR2_CVAL_AUDIOMODE_MONO: - return V4L2_TUNER_MODE_MONO; - case PVR2_CVAL_AUDIOMODE_STEREO: - return V4L2_TUNER_MODE_STEREO; - case PVR2_CVAL_AUDIOMODE_SAP: - return V4L2_TUNER_MODE_SAP; - case PVR2_CVAL_AUDIOMODE_LANG1: - return V4L2_TUNER_MODE_LANG1; - case PVR2_CVAL_AUDIOMODE_LANG2: - return V4L2_TUNER_MODE_LANG2; - case PVR2_CVAL_AUDIOMODE_LANG1_LANG2: - return V4L2_TUNER_MODE_LANG1_LANG2; - } - return V4L2_TUNER_MODE_STEREO; -} - - /* This function selects the correct audio input source */ static void set_stereo(struct pvr2_msp3400_handler *ctxt) { @@ -68,8 +48,7 @@ static void set_stereo(struct pvr2_msp3400_handler *ctxt) if (hdw->controls[PVR2_CID_INPUT].value == PVR2_CVAL_INPUT_TV) { struct v4l2_tuner vt; memset(&vt,0,sizeof(vt)); - vt.audmode = xlat_audiomode_to_v4l2( - hdw->controls[PVR2_CID_AUDIOMODE].value); + vt.audmode = hdw->controls[PVR2_CID_AUDIOMODE].value; pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_TUNER,&vt); } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c index 60ee45ca2..78bc968c0 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c @@ -27,56 +27,7 @@ #define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__) -/* - - isely@pobox.com 16-Oct-2005 - There are two method by which we can - theoretically retrieve information from the device's eeprom: - - Method #1: We expect tveeprom to attach to our I2C adapter as a - client, in which case we send it a command to tell us what it - knows about the device. This is the "indirect" method. - - Method #2: We retrieve the eeprom contents ourselves and call into - tveeprom_hauppauge_analog() to parse the data and tell us what - it knows about the device. This is the "direct" method. - - Unfortunately it isn't perfectly clear which method is the best. - They each have pros and cons: - - #1 is simpler & more portable and has an API which is more stable. - - #1 doesn't provide as much information as #2 does. For example, we - can't retrieve the device's serial number with method #1. - - #1 requires that tveeprom.ko autonomously detect the eeprom chip on - its own; we can't help it out here. Worse still, it seems that - the eeprom in some PVR USB2 devices (like mine) can't be detected - correctly (I don't see an ack on a zero length write which is - what the I2C core attempts). - - #2 uses an unstable API. Current the ivtv implementation of #2 uses - a completely different tveeprom struct than the v4l - implementation of #2. This causes a usability nightmare. - - Since I can't decide, both methods are implemented below. Method #2 - (direct) is the default choice, but if you want to try method #1, - then define PVR2_EEPROM_INDIRECT and cross your fingers... - If you use method #1, please be aware that you won't have a serial - number for the device and thus the sysfs interface may be a little - different. In addition, if tveeprom.ko fails to detect the eeprom - you may have to force it using standard i2c module options (try - force=-1,80). FINALLY (and this may foreclose this option for you - completely), the PVR USB2 eeprom seems to have valid data only in - the upper 128 bytes - the lower 128 bytes causes tveeprom.ko to - abort. In method #2 we only read the upper 128 bytes... - - */ - - - - -/* Stuff common to direct approach of operation tveeprom */ /* @@ -121,7 +72,7 @@ static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw) /* FX2 documentation states that a 16bit-addressed eeprom is expected if the I2C address is an odd number (yeah, this is - strange bit it's what they do) */ + strange but it's what they do) */ mode16 = (addr & 1); eepromSize = (mode16 ? 4096 : 256); trace_eeprom("Examining %d byte eeprom at location 0x%x" @@ -165,15 +116,7 @@ static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw) } -/*VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV*/ -/* BEGIN DIRECT METHOD, V4L ONLY */ - - -/* Directly call eeprom analysis function within tveeprom. This - version directly assumes it is talking to the V4L version of - tveeprom.ko and does not attempt anything ugly to maintain - backwards compatibility. */ - +/* Directly call eeprom analysis function within tveeprom. */ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw) { u8 *eeprom; @@ -204,66 +147,13 @@ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw) trace_eeprom("rev_str=%s",tvdata.rev_str); hdw->tuner_type = tvdata.tuner_type; hdw->serial_number = tvdata.serial_number; - hdw->video_standards = tvdata.tuner_formats; + pvr2_hdw_internal_set_std_avail(hdw,tvdata.tuner_formats); kfree(eeprom); return 0; } - - -/* END DIRECT METHOD, V4L ONLY */ -/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - - - - - - - -static v4l2_std_id std_choices[] = { - [PVR2_CVAL_VIDEOSTANDARD_NTSC_M] = V4L2_STD_NTSC_M, - [PVR2_CVAL_VIDEOSTANDARD_PAL_BG] = V4L2_STD_PAL_BG, - [PVR2_CVAL_VIDEOSTANDARD_PAL_I] = V4L2_STD_PAL_I, - [PVR2_CVAL_VIDEOSTANDARD_PAL_DK] = V4L2_STD_PAL_DK, - [PVR2_CVAL_VIDEOSTANDARD_SECAM_L] = V4L2_STD_SECAM_L, - [PVR2_CVAL_VIDEOSTANDARD_PAL_M] = V4L2_STD_PAL_M, -}; - -void pvr2_eeprom_set_default_standard(struct pvr2_hdw *hdw) -{ - int vstd_value = 0; - int vstd_found = 0; - unsigned int idx; - v4l2_std_id vs = (v4l2_std_id)hdw->video_standards; - - for (idx = 0; idx < sizeof(std_choices)/sizeof(std_choices[0]); - idx++) { - if (!(vs & std_choices[idx])) continue; - trace_eeprom("Detected video standard %s (from eeprom)", - pvr2_hdw_get_ctl_value_name( - hdw,PVR2_CID_VIDEOSTANDARD,idx)); - if (vstd_found) continue; - vstd_value = idx; - vstd_found = !0; - } - - if (!vstd_found) { - trace_eeprom("eeprom unable to recognize" - " a known video standard"); - return; - } - - trace_eeprom("Setting initial video standard to %s" - " (detected from eeprom)", - pvr2_hdw_get_ctl_value_name(hdw, - PVR2_CID_VIDEOSTANDARD, - vstd_value)); - pvr2_hdw_set_ctl_value_internal(hdw,PVR2_CID_VIDEOSTANDARD,vstd_value); -} - - /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.h b/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.h index 061cecd91..84242975d 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.h @@ -26,7 +26,6 @@ struct pvr2_hdw; int pvr2_eeprom_analyze(struct pvr2_hdw *); -void pvr2_eeprom_set_default_standard(struct pvr2_hdw *); #endif /* __PVRUSB2_EEPROM_H */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c index b85ef5059..2a93bcc96 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -268,26 +268,22 @@ static int pvr2_write_encoder_vcmd (struct pvr2_hdw *hdw, u8 cmd, int pvr2_encoder_configure(struct pvr2_hdw *hdw) { int ret = 0, audio, i; - int vd_std = hdw->controls[PVR2_CID_VIDEOSTANDARD].value; + int vd_std = hdw->controls[PVR2_CID_STDCUR].value; int height = hdw->controls[PVR2_CID_VRES].value; int width = hdw->controls[PVR2_CID_HRES].value; int height_full = !hdw->controls[PVR2_CID_INTERLACE].value; int is_30fps, is_ntsc; - switch (vd_std) { - case PVR2_CVAL_VIDEOSTANDARD_NTSC_M: + if (vd_std & V4L2_STD_NTSC) { is_ntsc=1; is_30fps=1; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_M: + } else if (vd_std & V4L2_STD_PAL_M) { is_ntsc=0; is_30fps=1; - break; - default: + } else { is_ntsc=0; is_30fps=0; - break; } pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 05e44385b..9c5f0f74c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -45,6 +45,83 @@ #include "pvrusb2-hdw.h" #include "pvrusb2-io.h" + +/* Definition of state variables that we can inspect & change. Numbers are + assigned from zero counting up with no gaps. */ +#define PVR2_CID_BRIGHTNESS 0 +#define PVR2_CID_CONTRAST 1 +#define PVR2_CID_SATURATION 2 +#define PVR2_CID_HUE 3 +#define PVR2_CID_VOLUME 4 +#define PVR2_CID_BALANCE 5 +#define PVR2_CID_BASS 6 +#define PVR2_CID_TREBLE 7 +#define PVR2_CID_MUTE 8 +#define PVR2_CID_SRATE 9 +#define PVR2_CID_AUDIOBITRATE 10 +#define PVR2_CID_AUDIOCRC 11 +#define PVR2_CID_AUDIOEMPHASIS 12 +#define PVR2_CID_VBR 13 +#define PVR2_CID_AVERAGEVIDEOBITRATE 14 +#define PVR2_CID_PEAKVIDEOBITRATE 15 +#define PVR2_CID_STDAVAIL 16 // V4L2 video standard bit mask +#define PVR2_CID_INPUT 17 +#define PVR2_CID_AUDIOMODE 18 // V4L2 standard audio mode enum +#define PVR2_CID_FREQUENCY 19 // Units of Hz +#define PVR2_CID_HRES 20 +#define PVR2_CID_VRES 21 +#define PVR2_CID_INTERLACE 22 +#define PVR2_CID_AUDIOLAYER 23 +#define PVR2_CID_CHANNEL 24 +#define PVR2_CID_CHANPROG_ID 25 +#define PVR2_CID_CHANPROG_FREQ 26 +#define PVR2_CID_SIGNAL_PRESENT 27 +#define PVR2_CID_STREAMING_ENABLED 28 +#define PVR2_CID_HSM 29 +#define PVR2_CID_SUBSYS_MASK 30 +#define PVR2_CID_SUBSYS_STREAM_MASK 31 +#define PVR2_CID_STDCUR 32 // V4L2 video standard bit mask +#define PVR2_CID_STDNAME 33 // Enumeration of available standards + +/* Legal values for the SRATE state variable */ +#define PVR2_CVAL_SRATE_48 0 +#define PVR2_CVAL_SRATE_44_1 1 +#define PVR2_CVAL_SRATE_MIN PVR2_CVAL_SRATE_48 +#define PVR2_CVAL_SRATE_MAX PVR2_CVAL_SRATE_44_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 +#define PVR2_CVAL_AUDIOBITRATE_MIN PVR2_CVAL_AUDIOBITRATE_384 +#define PVR2_CVAL_AUDIOBITRATE_MAX PVR2_CVAL_AUDIOBITRATE_VBR + +/* 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 +#define PVR2_CVAL_AUDIOEMPHASIS_MIN PVR2_CVAL_AUDIOEMPHASIS_NONE +#define PVR2_CVAL_AUDIOEMPHASIS_MAX PVR2_CVAL_AUDIOEMPHASIS_CCITT + +/* 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_CVAL_HSM_MIN PVR2_CVAL_HSM_FAIL +#define PVR2_CVAL_HSM_MAX PVR2_CVAL_HSM_HIGH + #define PVR2_VID_ENDPOINT 0x84 #define PVR2_UNK_ENDPOINT 0x86 /* maybe raw yuv ? */ #define PVR2_VBI_ENDPOINT 0x88 @@ -58,7 +135,33 @@ struct pvr2_decoder; -struct pvr2_ctl_state { +struct pvr2_ctl_def; +struct pvr2_ctrl; + +typedef int (*pvr2_ctl_set_func)(struct pvr2_ctrl *,int val); +typedef int (*pvr2_ctl_get_func)(struct pvr2_ctrl *); + +struct pvr2_ctl_def { + int id; + const char *name; + const char *desc; + pvr2_ctl_set_func set_func; + pvr2_ctl_get_func get_func; + int mask_value; + int max_value; + int min_value; + int skip_init; + int default_value; + int is_valid; + const char **value_defs_ptr; + unsigned int value_defs_count; +}; + + +struct pvr2_ctrl { + struct pvr2_hdw *hdw; + const struct pvr2_ctl_def *ctl_def; + int is_valid; int value; int dirty; }; @@ -96,7 +199,9 @@ struct pvr2_decoder_ctrl { /* 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 /* This structure contains all state data directly needed to manipulate the hardware (as opposed to complying with a kernel @@ -191,7 +296,13 @@ struct pvr2_hdw { /* Tuner / frequency control stuff */ unsigned int tuner_type; int tuner_updated; - unsigned long video_standards; + v4l2_std_id video_std_avail; + v4l2_std_id video_std_cur; + struct pvr2_ctl_def video_std_enum; + struct v4l2_standard *std_defs; + const char **video_std_names; + unsigned int std_cnt; + int std_id; int unit_number; /* ID for driver instance */ unsigned long serial_number; /* ID for hardware itself */ @@ -211,13 +322,17 @@ struct pvr2_hdw { struct pvr2_audio_stat *audio_stat; /* Every last bit of controllable state */ - struct pvr2_ctl_state controls[PVR2_CID_COUNT]; + struct pvr2_ctrl *controls; }; -int pvr2_hdw_set_ctl_value_internal(struct pvr2_hdw *hdw, - unsigned int ctl_id,int value); int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw); +int pvr2_ctrl_internal_set_value(struct pvr2_ctrl *cptr,int val); +int pvr2_ctrl_internal_get_value(struct pvr2_ctrl *cptr); + +int pvr2_hdw_internal_set_stdenum_cur(struct pvr2_hdw *hdw,int val); +void pvr2_hdw_internal_set_std_cur(struct pvr2_hdw *hdw,int msk); +void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw,int msk); #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 ec2b5eeae..f0de1e154 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -24,6 +24,7 @@ #include <linux/string.h> #include <linux/slab.h> #include <linux/firmware.h> +#include <linux/videodev2.h> #include <asm/semaphore.h> #include "pvrusb2.h" #include "pvrusb2-util.h" @@ -37,7 +38,9 @@ struct usb_device_id pvr2_device_table[] = { [PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) }, +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX [PVR2_HDW_TYPE_24XXX] = { USB_DEVICE(0x2040, 0x2400) }, +#endif { } }; @@ -45,7 +48,9 @@ MODULE_DEVICE_TABLE(usb, pvr2_device_table); static const char *pvr2_device_names[] = { [PVR2_HDW_TYPE_29XXX] = "WinTV PVR USB2 Model Category 29xxxx", +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX [PVR2_HDW_TYPE_24XXX] = "WinTV PVR USB2 Model Category 24xxxx", +#endif }; static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = 0}; @@ -86,22 +91,6 @@ MODULE_PARM_DESC(tolerance,"specify stream error tolerance"); /* size of a firmware chunk */ #define FIRMWARE_CHUNK_SIZE 0x2000 -typedef int (*pvr2_ctl_set_func)(struct pvr2_hdw *,int ctl_id,int val); -typedef int (*pvr2_ctl_get_func)(struct pvr2_hdw *,int ctl_id); - -struct pvr2_ctl_def { - const char *name; - pvr2_ctl_set_func set_func; - pvr2_ctl_get_func get_func; - int max_value; - int min_value; - int skip_init; - int default_value; - const char **value_defs_ptr; - unsigned int value_defs_count; -}; - - static const char *control_values_srate[] = { [PVR2_CVAL_SRATE_48] = "48KHz", [PVR2_CVAL_SRATE_44_1] = "44.1KHz", @@ -135,12 +124,35 @@ static const char *control_values_audioemphasis[] = { static const char *control_values_videostandard[] = { - [PVR2_CVAL_VIDEOSTANDARD_NTSC_M] = "NTSC-M", - [PVR2_CVAL_VIDEOSTANDARD_SECAM_L] = "SECAM-L", - [PVR2_CVAL_VIDEOSTANDARD_PAL_BG] = "PAL-BG", - [PVR2_CVAL_VIDEOSTANDARD_PAL_I] = "PAL-I", - [PVR2_CVAL_VIDEOSTANDARD_PAL_DK] = "PAL-DK", - [PVR2_CVAL_VIDEOSTANDARD_PAL_M] = "PAL-M", + "PAL-B", + "PAL-B1", + "PAL-G", + "PAL-H", + + "PAL-I", + "PAL-D", + "PAL-D1", + "PAL-K", + + "PAL-M", + "PAL-N", + "PAL-Nc", + "PAL-60", + + "NTSC-M", + "NTSC-M-JP", + "NTSC-443", + 0, + + "SECAM-B", + "SECAM-D", + "SECAM-G", + "SECAM-H", + + "SECAM-K", + "SECAM-K1", + "SECAM-L", + "SECAM-LC", }; @@ -153,12 +165,11 @@ static const char *control_values_input[] = { static const char *control_values_audiomode[] = { - [PVR2_CVAL_AUDIOMODE_MONO] = "Mono", - [PVR2_CVAL_AUDIOMODE_STEREO] = "Stereo", - [PVR2_CVAL_AUDIOMODE_SAP] = "SAP", - [PVR2_CVAL_AUDIOMODE_LANG1] = "Lang1", - [PVR2_CVAL_AUDIOMODE_LANG2] = "Lang2", - [PVR2_CVAL_AUDIOMODE_LANG1_LANG2] = "Lang1+Lang2", + [V4L2_TUNER_MODE_MONO] = "Mono", + [V4L2_TUNER_MODE_STEREO] = "Stereo", + [V4L2_TUNER_MODE_LANG1] = "Lang1", + [V4L2_TUNER_MODE_LANG2] = "Lang2", + [V4L2_TUNER_MODE_LANG1_LANG2] = "Lang1+Lang2", }; @@ -173,183 +184,265 @@ static const char *control_values_hsm[] = { .value_defs_ptr = x, \ .value_defs_count = (sizeof(x)/sizeof(x[0])) -static int pvr2_ctl_set_chanprog_id(struct pvr2_hdw *hdw,int ctl_id,int value); -static int pvr2_ctl_get_chanprog_id(struct pvr2_hdw *hdw,int ctl_id); -static int pvr2_ctl_get_signal(struct pvr2_hdw *hdw,int ctl_id); -static int pvr2_ctl_get_streaming(struct pvr2_hdw *hdw,int ctl_id); -static int pvr2_ctl_get_hsm(struct pvr2_hdw *hdw,int ctl_id); -static int pvr2_ctl_get_subsys_mask(struct pvr2_hdw *hdw,int ctl_id); -static int pvr2_ctl_set_subsys_mask(struct pvr2_hdw *hdw,int ctl_id,int val); -static int pvr2_ctl_get_subsys_stream_mask(struct pvr2_hdw *hdw,int ctl_id); -static int pvr2_ctl_set_subsys_stream_mask(struct pvr2_hdw *hdw,int ctl_id, - int val); - -static struct pvr2_ctl_def control_defs[PVR2_CID_COUNT] = +static int pvr2_ctl_set_chanprog_id(struct pvr2_ctrl *cptr,int value); +static int pvr2_ctl_get_chanprog_id(struct pvr2_ctrl *cptr); +static int pvr2_ctl_get_signal(struct pvr2_ctrl *cptr); +static int pvr2_ctl_get_streaming(struct pvr2_ctrl *cptr); +static int pvr2_ctl_get_hsm(struct pvr2_ctrl *cptr); +static int pvr2_ctl_get_subsys_mask(struct pvr2_ctrl *cptr); +static int pvr2_ctl_set_subsys_mask(struct pvr2_ctrl *cptr,int val); +static int pvr2_ctl_get_subsys_stream_mask(struct pvr2_ctrl *cptr); +static int pvr2_ctl_set_subsys_stream_mask(struct pvr2_ctrl *cptr,int val); +static int pvr2_ctl_set_stdcur(struct pvr2_ctrl *cptr,int val); +static int pvr2_ctl_get_stdcur(struct pvr2_ctrl *cptr); +static int pvr2_ctl_get_stdavail(struct pvr2_ctrl *cptr); +static int pvr2_ctl_set_stdenumcur(struct pvr2_ctrl *cptr,int val); +static int pvr2_ctl_get_stdenumcur(struct pvr2_ctrl *cptr); + +static struct pvr2_ctl_def control_defs[] = { [PVR2_CID_BRIGHTNESS] = { - .name = "Brightness", + .id = V4L2_CID_BRIGHTNESS, + .is_valid = !0, + .desc = "Brightness", + .name = "brightness", .min_value = 0, .max_value = 255, .default_value = 128, }, [PVR2_CID_CONTRAST] = { - .name = "Contrast", + .id = V4L2_CID_CONTRAST, + .is_valid = !0, + .desc = "Contrast", + .name = "contrast", .min_value = 0, .max_value = 127, .default_value = 68, }, [PVR2_CID_SATURATION] = { - .name = "Saturation", + .id = V4L2_CID_SATURATION, + .is_valid = !0, + .desc = "Saturation", + .name = "saturation", .min_value = 0, .max_value = 127, .default_value = 64, }, [PVR2_CID_HUE] = { - .name = "Hue", + .id = V4L2_CID_HUE, + .is_valid = !0, + .desc = "Hue", + .name = "hue", .min_value = -128, .max_value = 127, .default_value = 0, }, [PVR2_CID_VOLUME] = { - .name = "Volume", + .id = V4L2_CID_AUDIO_VOLUME, + .is_valid = !0, + .desc = "Volume", + .name = "volume", .min_value = 0, .max_value = 65535, .default_value = 65535, }, [PVR2_CID_BALANCE] = { - .name = "Balance", + .id = V4L2_CID_AUDIO_BALANCE, + .is_valid = !0, + .desc = "Balance", + .name = "balance", .min_value = -32768, .max_value = 32767, .default_value = 0, }, [PVR2_CID_BASS] = { - .name = "Bass", + .id = V4L2_CID_AUDIO_BASS, + .is_valid = !0, + .desc = "Bass", + .name = "bass", .min_value = -32768, .max_value = 32767, .default_value = 0, }, [PVR2_CID_TREBLE] = { - .name = "Treble", + .id = V4L2_CID_AUDIO_TREBLE, + .is_valid = !0, + .desc = "Treble", + .name = "treble", .min_value = -32768, .max_value = 32767, .default_value = 0, }, [PVR2_CID_MUTE] = { - .name = "Mute", + .id = V4L2_CID_AUDIO_MUTE, + .is_valid = !0, + .desc = "Mute", + .name = "mute", .min_value = 0, .max_value = 1, .default_value = 0, }, [PVR2_CID_SRATE] = { - .name = "Sample rate", + .id = V4L2_CID_PVR_SRATE, + .is_valid = !0, + .desc = "Sample rate", + .name = "srate", .min_value = PVR2_CVAL_SRATE_MIN, .max_value = PVR2_CVAL_SRATE_MAX, .default_value = PVR2_CVAL_SRATE_48, VDEF(control_values_srate), }, [PVR2_CID_AUDIOBITRATE] = { - .name = "Audio Bitrate", + .id = V4L2_CID_PVR_AUDIOBITRATE, + .is_valid = !0, + .desc = "Audio Bitrate", + .name = "audio_bitrate", .min_value = PVR2_CVAL_AUDIOBITRATE_MIN, .max_value = PVR2_CVAL_AUDIOBITRATE_MAX, .default_value = PVR2_CVAL_AUDIOBITRATE_224, VDEF(control_values_audiobitrate), }, [PVR2_CID_AUDIOCRC] = { - .name = "Audio CRC", + .id = V4L2_CID_PVR_AUDIOCRC, + .is_valid = !0, + .desc = "Audio CRC", + .name = "audio_crc", .min_value = 0, .max_value = 1, .default_value = 1, }, [PVR2_CID_AUDIOEMPHASIS] = { - .name = "Audio Emphasis", + .id = V4L2_CID_PVR_AUDIOEMPHASIS, + .is_valid = !0, + .desc = "Audio Emphasis", + .name = "audio_emphasis", .min_value = PVR2_CVAL_AUDIOEMPHASIS_MIN, .max_value = PVR2_CVAL_AUDIOEMPHASIS_MAX, .default_value = PVR2_CVAL_AUDIOEMPHASIS_NONE, VDEF(control_values_audioemphasis), }, [PVR2_CID_VBR] = { - .name = "Variable video bitrate", + .id = V4L2_CID_PVR_VBR, + .is_valid = !0, + .desc = "Variable video bitrate", + .name = "vbr", .min_value = 0, .max_value = 1, .default_value = 0, }, [PVR2_CID_AVERAGEVIDEOBITRATE] = { - .name = "Average video bitrate", + .id = V4L2_CID_PVR_VIDEOBITRATE, + .is_valid = !0, + .desc = "Average video bitrate", + .name = "video_average_bitrate", .min_value = 1, .max_value = 20000000, .default_value = 6000000, }, [PVR2_CID_PEAKVIDEOBITRATE] = { - .name = "Peak video bitrate", + .id = V4L2_CID_PVR_VIDEOPEAK, + .is_valid = !0, + .desc = "Peak video bitrate", + .name = "video_peak_bitrate", .min_value = 1, .max_value = 20000000, .default_value = 6000000, }, - [PVR2_CID_VIDEOSTANDARD] = { - .name = "Video Standard", - .min_value = PVR2_CVAL_VIDEOSTANDARD_MIN, - .max_value = PVR2_CVAL_VIDEOSTANDARD_MAX, - .default_value = PVR2_CVAL_VIDEOSTANDARD_NTSC_M, + [PVR2_CID_STDAVAIL] = { + .is_valid = !0, + .desc = "Video Standards Available Mask", + .name = "video_standard_mask_available", + .min_value = 0, + .max_value = 0, + .default_value = (int)V4L2_STD_UNKNOWN, + .mask_value = (int)V4L2_STD_ALL, + .get_func = pvr2_ctl_get_stdavail, VDEF(control_values_videostandard), }, [PVR2_CID_INPUT] = { - .name = "Video Source", + .id = V4L2_CID_PVR_INPUT, + .is_valid = !0, + .desc = "Video Source", + .name = "input", .min_value = PVR2_CVAL_INPUT_MIN, .max_value = PVR2_CVAL_INPUT_MAX, .default_value = PVR2_CVAL_INPUT_TV, VDEF(control_values_input), }, [PVR2_CID_AUDIOMODE] = { - .name = "Audio Mode", - .min_value = PVR2_CVAL_AUDIOMODE_MIN, - .max_value = PVR2_CVAL_AUDIOMODE_MAX, - .default_value = PVR2_CVAL_AUDIOMODE_STEREO, + .id = V4L2_CID_PVR_AUDIOMODE, + .is_valid = !0, + .desc = "Audio Mode", + .name = "audio_mode", + .min_value = V4L2_TUNER_MODE_MONO, + .max_value = V4L2_TUNER_MODE_LANG1_LANG2, + .default_value = V4L2_TUNER_MODE_STEREO, VDEF(control_values_audiomode), }, [PVR2_CID_FREQUENCY] = { - .name = "Tuner Frequency (Hz)", + .id = V4L2_CID_PVR_FREQUENCY, + .is_valid = !0, + .desc = "Tuner Frequency (Hz)", + .name = "frequency", .min_value = 55250000L, .max_value = 850000000L, .default_value = 175250000L, }, [PVR2_CID_HRES] = { - .name = "Horizontal capture resolution", + .id = V4L2_CID_PVR_HRES, + .is_valid = !0, + .desc = "Horizontal capture resolution", + .name = "resolution_hor", .min_value = 320, .max_value = 720, .default_value = 720, }, [PVR2_CID_VRES] = { - .name = "Vertical capture resolution", + .id = V4L2_CID_PVR_VRES, + .is_valid = !0, + .desc = "Vertical capture resolution", + .name = "resolution_ver", .min_value = 200, .max_value = 625, .default_value = 480, }, [PVR2_CID_INTERLACE] = { - .name = "Interlace mode", + .id = V4L2_CID_PVR_INTERLACE, + .is_valid = !0, + .desc = "Interlace mode", + .name = "interlace", .min_value = 0, .max_value = 1, .default_value = 0, }, [PVR2_CID_AUDIOLAYER] = { - .name = "Audio Layer", + .is_valid = !0, + .desc = "Audio Layer", + .name = "audio_layer", .min_value = 0, /* This is all a wild guess */ .max_value = 3, .default_value = 2, /* Appears to be all that is supported */ }, [PVR2_CID_CHANNEL] = { - .name = "Channel", + .is_valid = !0, + .desc = "Channel", + .name = "channel", .min_value = 0, .max_value = FREQTABLE_SIZE, .default_value = 0, }, [PVR2_CID_CHANPROG_ID] = { - .name = "Channel Program ID", + .is_valid = !0, + .desc = "Channel Program ID", + .name = "freq_table_channel", .min_value = 0, .max_value = FREQTABLE_SIZE, .default_value = 0, }, [PVR2_CID_CHANPROG_FREQ] = { - .name = "Channel Program Frequency", + .is_valid = !0, + .desc = "Channel Program Frequency", + .name = "freq_table_value", .min_value = 55250000L, .max_value = 850000000L, .skip_init = !0, @@ -357,26 +450,34 @@ static struct pvr2_ctl_def control_defs[PVR2_CID_COUNT] = .get_func = pvr2_ctl_get_chanprog_id, }, [PVR2_CID_SIGNAL_PRESENT] = { - .name = "Signal Present", + .is_valid = !0, + .desc = "Signal Present", + .name = "signal_present", .min_value = 0, .max_value = 1, .get_func = pvr2_ctl_get_signal, }, [PVR2_CID_STREAMING_ENABLED] = { - .name = "Streaming Enabled", + .is_valid = !0, + .desc = "Streaming Enabled", + .name = "streaming_enabled", .min_value = 0, .max_value = 1, .get_func = pvr2_ctl_get_streaming, }, [PVR2_CID_HSM] = { - .name = "USB Speed", + .is_valid = !0, + .desc = "USB Speed", + .name = "usb_speed", .min_value = PVR2_CVAL_HSM_MIN, .max_value = PVR2_CVAL_HSM_MAX, .get_func = pvr2_ctl_get_hsm, VDEF(control_values_hsm), }, [PVR2_CID_SUBSYS_MASK] = { - .name = "Subsystem enabled mask", + .is_valid = !0, + .desc = "Subsystem enabled mask", + .name = "debug_subsys_mask", .min_value = 0, .max_value = 0x7fffffff, .skip_init = !0, @@ -384,17 +485,34 @@ static struct pvr2_ctl_def control_defs[PVR2_CID_COUNT] = .set_func = pvr2_ctl_set_subsys_mask, }, [PVR2_CID_SUBSYS_STREAM_MASK] = { - .name = "Subsystem stream mask", + .is_valid = !0, + .desc = "Subsystem stream mask", + .name = "debug_subsys_stream_mask", .min_value = 0, .max_value = 0x7fffffff, .skip_init = !0, .get_func = pvr2_ctl_get_subsys_stream_mask, .set_func = pvr2_ctl_set_subsys_stream_mask, }, + [PVR2_CID_STDCUR] = { + .id = V4L2_CID_PVR_STDCUR, + .is_valid = !0, + .desc = "Video Standard In Use Mask", + .name = "video_standard_mask_active", + .min_value = 0, + .max_value = 0, + .default_value = (int)V4L2_STD_UNKNOWN, + .mask_value = (int)V4L2_STD_ALL, + .set_func = pvr2_ctl_set_stdcur, + .get_func = pvr2_ctl_get_stdcur, + VDEF(control_values_videostandard), + }, }; #undef VDEF +#define CTRL_DEF_COUNT (sizeof(control_defs)/sizeof(control_defs[0])) +#define CTRL_COUNT CTRL_DEF_COUNT+1 const char *pvr2_config_get_name(enum pvr2_config cfg) { @@ -511,9 +629,11 @@ int pvr2_upload_firmware1(struct pvr2_hdw *hdw) static const char *fw_files_29xxx[] = { "v4l-pvrusb2-29xxx-01.fw", }; +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX static const char *fw_files_24xxx[] = { "v4l-pvrusb2-24xxx-01.fw", }; +#endif static const struct { const char **lst; unsigned int cnt; @@ -522,10 +642,12 @@ int pvr2_upload_firmware1(struct pvr2_hdw *hdw) fw_files_29xxx, sizeof(fw_files_29xxx)/sizeof(fw_files_29xxx[0]), }, +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX [PVR2_HDW_TYPE_24XXX] = { fw_files_24xxx, sizeof(fw_files_24xxx)/sizeof(fw_files_24xxx[0]), }, +#endif }; hdw->fw1_state = FW1_STATE_FAILED; // default result @@ -944,9 +1066,9 @@ void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw, } -static int pvr2_ctl_get_streaming(struct pvr2_hdw *hdw,int ctl_id) +static int pvr2_ctl_get_streaming(struct pvr2_ctrl *cptr) { - return hdw->flag_streaming_enabled != 0; + return cptr->hdw->flag_streaming_enabled != 0; } @@ -1061,6 +1183,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) { int ret; unsigned int idx; + struct pvr2_ctrl *cptr; int reloadFl = 0; if (!reloadFl) { reloadFl = (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints @@ -1106,14 +1229,17 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) pvr2_i2c_core_init(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; - for (idx = 0; idx < PVR2_CID_COUNT; idx++) { - if (control_defs[idx].skip_init) continue; - pvr2_hdw_set_ctl_value_internal( - hdw,idx,control_defs[idx].default_value); + for (idx = 0; idx < CTRL_COUNT; idx++) { + cptr = hdw->controls + idx; + if (!pvr2_ctrl_is_valid(cptr)) continue; + if (cptr->ctl_def->skip_init) continue; + pvr2_ctrl_internal_set_value(cptr, + cptr->ctl_def->default_value); } - pvr2_reset_ctl_endpoints(hdw); - if (!pvr2_hdw_dev_ok(hdw)) return; + // Do not use pvr2_reset_ctl_endpoints() here. It is not + // thread-safe against the normal pvr2_send_request() mechanism. + // (We should make it thread safe). ret = pvr2_hdw_get_eeprom_addr(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; @@ -1138,7 +1264,21 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) if (!pvr2_hdw_dev_ok(hdw)) return; - pvr2_eeprom_set_default_standard(hdw); + for (idx = 0; idx < hdw->std_cnt; idx++) { + pvr2_trace(PVR2_TRACE_EEPROM, + "Detected video standard %s (from eeprom)", + hdw->std_defs[idx].name); + } + if (hdw->std_cnt) { + pvr2_trace(PVR2_TRACE_EEPROM, + "Initial video standard set to %s" + " (detected from eeprom)", + hdw->std_defs[hdw->std_id].name); + } else { + pvr2_trace(PVR2_TRACE_EEPROM, + "Unable to select a viable video standard"); + } + if (!pvr2_hdw_dev_ok(hdw)) return; pvr2_hdw_commit_ctl_internal(hdw); @@ -1259,8 +1399,35 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw,pvr2_device_names[hdw_type]); if (!hdw) goto fail; memset(hdw,0,sizeof(*hdw)); + + // Initialize video standard enum dynamic control + hdw->video_std_enum.name = "video_standard"; + hdw->video_std_enum.desc = "Video Standard Name"; + hdw->video_std_enum.id = 0; // ????? + hdw->video_std_enum.set_func = pvr2_ctl_set_stdenumcur; + hdw->video_std_enum.get_func = pvr2_ctl_get_stdenumcur; + hdw->video_std_enum.mask_value = 0; + hdw->video_std_enum.max_value = 0; + hdw->video_std_enum.min_value = 0; + hdw->video_std_enum.default_value = 0; + hdw->video_std_enum.is_valid = !0; + + hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * CTRL_COUNT, + GFP_KERNEL); + if (!hdw->controls) goto fail; + memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * CTRL_COUNT); hdw->hdw_type = hdw_type; + for (idx = 0; idx < CTRL_DEF_COUNT; idx++) { + hdw->controls[idx].hdw = hdw; + hdw->controls[idx].ctl_def = control_defs + idx; + hdw->controls[idx].is_valid = + hdw->controls[idx].ctl_def->is_valid; + } + hdw->controls[PVR2_CID_STDNAME].hdw = hdw; + hdw->controls[PVR2_CID_STDNAME].ctl_def = &hdw->video_std_enum; + hdw->controls[PVR2_CID_STDNAME].is_valid = !0; + hdw->eeprom_addr = -1; hdw->unit_number = -1; hdw->v4l_minor_number = -1; @@ -1322,6 +1489,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, if (hdw->ctl_write_urb) usb_free_urb(hdw->ctl_write_urb); if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer); if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer); + if (hdw->controls) kfree(hdw->controls); kfree(hdw); } return 0; @@ -1386,6 +1554,9 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) unit_pointers[hdw->unit_number] = 0; } } while (0); up(&pvr2_unit_sem); + kfree(hdw->controls); + if (hdw->std_defs) kfree(hdw->std_defs); + if (hdw->video_std_names) kfree(hdw->video_std_names); kfree(hdw); } @@ -1414,10 +1585,11 @@ void pvr2_hdw_disconnect(struct pvr2_hdw *hdw) } -static int pvr2_ctl_set_chanprog_id(struct pvr2_hdw *hdw,int ctl_id,int value) +static int pvr2_ctl_set_chanprog_id(struct pvr2_ctrl *cptr,int value) { /* This is a special case; the value to store is to an array, and the element to select is determined by PVR_CID_CHANPROG_ID. */ + struct pvr2_hdw *hdw = cptr->hdw; int id = hdw->controls[PVR2_CID_CHANPROG_ID].value; if ((id < 1) || (id > FREQTABLE_SIZE)) return 0; hdw->freqTable[id-1] = value; @@ -1431,120 +1603,581 @@ static int pvr2_ctl_set_chanprog_id(struct pvr2_hdw *hdw,int ctl_id,int value) } -static int pvr2_ctl_get_chanprog_id(struct pvr2_hdw *hdw,int ctl_id) +static int pvr2_ctl_get_chanprog_id(struct pvr2_ctrl *cptr) { /* This is a special case; the value to return is from an array, and the element to select is determined by PVR_CID_CHANPROG_ID. */ + struct pvr2_hdw *hdw = cptr->hdw; int id = hdw->controls[PVR2_CID_CHANPROG_ID].value; if ((id < 1) || (id > FREQTABLE_SIZE)) return 0; return hdw->freqTable[id-1]; } +// Template data for possible enumerated video standards +static struct v4l2_standard pvr_standards[] = { + { + .id = V4L2_STD_PAL_BG, + .frameperiod = + { + .numerator = 1, + .denominator= 25 + }, + .framelines = 625, + .reserved = {0,0,0,0} + }, { + .id = V4L2_STD_PAL_I, + .frameperiod = + { + .numerator = 1, + .denominator= 25 + }, + .framelines = 625, + .reserved = {0,0,0,0} + }, { + .id = V4L2_STD_PAL_DK, + .frameperiod = + { + .numerator = 1, + .denominator= 25 + }, + .framelines = 625, + .reserved = {0,0,0,0} + }, { + .id = V4L2_STD_SECAM, + .frameperiod = + { + .numerator = 1, + .denominator= 25 + }, + .framelines = 625, + .reserved = {0,0,0,0} + }, { + .id = V4L2_STD_NTSC_M, + .frameperiod = + { + .numerator = 1001, + .denominator= 30000 + }, + .framelines = 525, + .reserved = {0,0,0,0} + }, { + .id = V4L2_STD_PAL_M, + .frameperiod = + { + .numerator = 1001, + .denominator= 30000 + }, + .framelines = 525, + .reserved = {0,0,0,0} + } +}; + +#define pvr_standards_cnt (sizeof(pvr_standards)/sizeof(pvr_standards[0])) -/* Retrieve current value for a given control */ -int pvr2_hdw_get_ctl_value(struct pvr2_hdw *hdw,unsigned int ctl_id) + +struct name_data { + struct v4l2_standard *std; + unsigned int bcnt; + unsigned int scnt; +}; + +static void name_build(struct name_data *dp,const char *str) { - int ret = 0; + if (!dp->bcnt) { + dp->bcnt = scnprintf(dp->std->name, + sizeof(dp->std->name)-1,"%s",str); + dp->scnt = 0; + return; + } - if (ctl_id >= PVR2_CID_COUNT) return 0; - LOCK_TAKE(hdw->big_lock); do { - if (control_defs[ctl_id].get_func) { - ret = control_defs[ctl_id].get_func(hdw,ctl_id); - break; + dp->bcnt += scnprintf(dp->std->name+dp->bcnt, + sizeof(dp->std->name)-(1+dp->bcnt), + "%s%s", + (dp->scnt ? "/" : "-"),str); + (dp->scnt)++; +} + +// Generate a descriptive name for a given standard +static void name_bucket(struct v4l2_standard *std) +{ + struct name_data nd; + nd.std = std; + nd.bcnt = 0; + if (std->id & (V4L2_STD_PAL_B| + V4L2_STD_PAL_B1| + V4L2_STD_PAL_G| + V4L2_STD_PAL_H| + V4L2_STD_PAL_I| + V4L2_STD_PAL_D| + V4L2_STD_PAL_D1| + V4L2_STD_PAL_K)) { + name_build(&nd,"PAL"); + if (std->id & V4L2_STD_PAL_B) name_build(&nd,"B"); + if (std->id & V4L2_STD_PAL_B1) name_build(&nd,"B1"); + if (std->id & V4L2_STD_PAL_D) name_build(&nd,"D"); + if (std->id & V4L2_STD_PAL_D1) name_build(&nd,"D1"); + if (std->id & V4L2_STD_PAL_G) name_build(&nd,"G"); + if (std->id & V4L2_STD_PAL_H) name_build(&nd,"H"); + if (std->id & V4L2_STD_PAL_I) name_build(&nd,"I"); + if (std->id & V4L2_STD_PAL_K) name_build(&nd,"K"); + if (std->id & V4L2_STD_PAL_M) name_build(&nd,"M"); + if (std->id & V4L2_STD_PAL_N) name_build(&nd,"N"); + if (std->id & V4L2_STD_PAL_Nc) name_build(&nd,"Nc"); + if (std->id & V4L2_STD_PAL_60) name_build(&nd,"60"); + std->name[nd.bcnt] = 0; + return; + } + if (std->id & (V4L2_STD_NTSC_M| + V4L2_STD_NTSC_M_JP| + V4L2_STD_NTSC_443)) { + name_build(&nd,"NTSC"); + if (std->id & V4L2_STD_NTSC_M) name_build(&nd,"M"); + if (std->id & V4L2_STD_NTSC_M_JP) name_build(&nd,"Mjp"); + if (std->id & V4L2_STD_NTSC_443) name_build(&nd,"443"); + std->name[nd.bcnt] = 0; + return; + } + if (std->id & (V4L2_STD_SECAM_B| + V4L2_STD_SECAM_D| + V4L2_STD_SECAM_G| + V4L2_STD_SECAM_H| + V4L2_STD_SECAM_K| + V4L2_STD_SECAM_K1| + V4L2_STD_SECAM_L| + V4L2_STD_SECAM_LC)) { + name_build(&nd,"SECAM"); + if (std->id & V4L2_STD_SECAM_B) name_build(&nd,"B"); + if (std->id & V4L2_STD_SECAM_D) name_build(&nd,"D"); + if (std->id & V4L2_STD_SECAM_G) name_build(&nd,"G"); + if (std->id & V4L2_STD_SECAM_H) name_build(&nd,"H"); + if (std->id & V4L2_STD_SECAM_K) name_build(&nd,"K"); + if (std->id & V4L2_STD_SECAM_K1) name_build(&nd,"K1"); + if (std->id & V4L2_STD_SECAM_L) name_build(&nd,"L"); + if (std->id & V4L2_STD_SECAM_LC) name_build(&nd,"LC"); + std->name[nd.bcnt] = 0; + return; + } + std->name[0] = 0; +} + + +// Given a mask of viable video standards to choose from, generate an +// appropriate array of v4l2_standard data that corresponds to it and set +// up related state in the driver to match. +void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw,int arg) +{ + v4l2_std_id buckets[pvr_standards_cnt]; + unsigned int idx1,idx2,std_cnt; + v4l2_std_id mmsk,amsk; + + amsk = (v4l2_std_id)arg; + + // Figure out which standard groups we can work with + std_cnt = 0; + mmsk = 0; + for (idx1 = 0; idx1 < pvr_standards_cnt; idx1++) { + buckets[idx1] = pvr_standards[idx1].id & amsk; + if (!buckets[idx1]) continue; + mmsk |= buckets[idx1]; + amsk &= ~buckets[idx1]; + std_cnt++; + } + + if (amsk) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Failed to bucketize the following standards: 0x%llx", + amsk); + } + + if (hdw->std_defs) { + kfree(hdw->std_defs); + hdw->std_defs = 0; + } + if (hdw->video_std_names) { + kfree(hdw->video_std_names); + hdw->video_std_names = 0; + } + hdw->std_cnt = 0; + + if (!std_cnt) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Failed to identify any viable standard groups"); + hdw->video_std_avail = 0; + pvr2_hdw_internal_set_std_cur(hdw,0); + return; + } + + if (std_cnt) { + // Allocate new video standard array + hdw->std_defs = kmalloc(sizeof(struct v4l2_standard) * std_cnt, + GFP_KERNEL); + hdw->std_cnt = std_cnt; + memset(hdw->std_defs,0,sizeof(struct v4l2_standard) * std_cnt); + hdw->video_std_names = kmalloc(sizeof(char *) * std_cnt, + GFP_KERNEL); + memset(hdw->video_std_names,0,sizeof(char *) * std_cnt); + idx2 = 0; + + // Initialize video standard array + for (idx1 = 0; idx1 < pvr_standards_cnt; idx1++) { + if (!buckets[idx1]) continue; + memcpy(hdw->std_defs + idx2, + pvr_standards + idx1, + sizeof(struct v4l2_standard)); + hdw->std_defs[idx2].id = buckets[idx1]; + idx2++; } - ret = hdw->controls[ctl_id].value; - } while(0); LOCK_GIVE(hdw->big_lock); - return ret; + + // Generate a name for each known video standard + for (idx1 = 0; idx1 < std_cnt; idx1++) { + name_bucket(hdw->std_defs + idx1); + hdw->video_std_names[idx1] = + hdw->std_defs[idx1].name; + } + + // Set up the dynamic control for this standard + hdw->video_std_enum.value_defs_ptr = hdw->video_std_names; + hdw->video_std_enum.value_defs_count = std_cnt; + } + + hdw->video_std_avail = mmsk; + if (!(hdw->video_std_avail & hdw->video_std_cur)) { + // Reselect standard if there isn't one that matches... + pvr2_hdw_internal_set_stdenum_cur(hdw,0); + } } -/* Return true if control is writable */ -int pvr2_hdw_get_ctl_rw(struct pvr2_hdw *hdw,unsigned int ctl_id) +unsigned int pvr2_hdw_get_stdenum_count(struct pvr2_hdw *hdw) { - if (ctl_id >= PVR2_CID_COUNT) return 0; - if (control_defs[ctl_id].get_func && !control_defs[ctl_id].set_func) { - return 0; + return hdw->std_cnt; +} + + +const struct v4l2_standard *pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw, + unsigned int idx) +{ + if (idx >= hdw->std_cnt) return 0; + return hdw->std_defs + idx; +} + + +int pvr2_hdw_internal_set_stdenum_cur(struct pvr2_hdw *hdw,int val) +{ + if (val < 0) return -EINVAL; + if (val >= hdw->std_cnt) return -EINVAL; + pvr2_hdw_internal_set_std_cur(hdw,hdw->std_defs[val].id); + return 0; +} + + +void pvr2_hdw_internal_set_std_cur(struct pvr2_hdw *hdw,int val) +{ + unsigned int idx; + v4l2_std_id msk,id; + + id = (v4l2_std_id)val; + // Only select from available standards + id &= hdw->video_std_avail; + + // Only select a single bit + for (idx = 0, msk = 1; msk; idx++, msk <<= 1) { + if (!(id & msk)) continue; + id = msk; + break; } - return !0; + + // Get out if nothing found + if (!msk) return; + + // Fix up standard group now + hdw->video_std_cur = id; + hdw->controls[PVR2_CID_STDCUR].value = id; + hdw->controls[PVR2_CID_STDCUR].dirty = !0; + for (idx = 0; idx < hdw->std_cnt; idx++) { + if (hdw->std_defs[idx].id & id) { + hdw->std_id = idx; + return; + } + } + + // Should never really get here, but just in case... + hdw->std_id = 0; } -/* Retrieve legal minimum value for a given control */ -int pvr2_hdw_get_ctl_min_value(struct pvr2_hdw *hdw,unsigned int ctl_id) +static int pvr2_ctl_set_stdcur(struct pvr2_ctrl *cptr,int val) { - if (ctl_id >= PVR2_CID_COUNT) return 0; - return control_defs[ctl_id].min_value; + pvr2_hdw_internal_set_std_cur(cptr->hdw,val); + return 0; +} + + +static int pvr2_ctl_get_stdcur(struct pvr2_ctrl *cptr) +{ + return (int)(cptr->hdw->video_std_cur); +} + + +static int pvr2_ctl_set_stdenumcur(struct pvr2_ctrl *cptr,int val) +{ + if (val < 0) return -EINVAL; + if (val >= cptr->hdw->std_cnt) return -EINVAL; + cptr->hdw->std_id = val; + pvr2_hdw_internal_set_std_cur(cptr->hdw, + cptr->hdw->std_id); + return 0; +} + + +static int pvr2_ctl_get_stdenumcur(struct pvr2_ctrl *cptr) +{ + return cptr->hdw->std_id; +} + + +static int pvr2_ctl_get_stdavail(struct pvr2_ctrl *cptr) +{ + return (int)(cptr->hdw->video_std_avail); +} + + +/* Get the number of defined controls */ +unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw) +{ + return CTRL_COUNT; +} + + +/* Retrieve a control handle given its index (0..count-1) */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *hdw, + unsigned int idx) +{ + if (idx < 0) return 0; + if (idx >= CTRL_COUNT) return 0; + return hdw->controls + idx; } -/* Retrieve legal maximum value for a given control */ -int pvr2_hdw_get_ctl_max_value(struct pvr2_hdw *hdw,unsigned int ctl_id) +/* Given an ID, retrieve the control structure associated with it. */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl(struct pvr2_hdw *hdw,unsigned int ctl_id) { - if (ctl_id >= PVR2_CID_COUNT) return 0; - return control_defs[ctl_id].max_value; + struct pvr2_ctrl *cptr; + unsigned int idx; + int i; + + /* This could be made a lot more efficient, but for now... */ + for (idx = 0; idx < CTRL_COUNT; idx++) { + cptr = hdw->controls + idx; + i = cptr->ctl_def->id; + if (i && (i == ctl_id)) return cptr; + } + + return 0; } -/* Set current value for given control - normally this is just stored and - the hardware isn't updated until the commit function is called. */ -int pvr2_hdw_set_ctl_value_internal(struct pvr2_hdw *hdw, - unsigned int ctl_id,int value) +/* Set the current value of a given control. This assumes we are already + inside our critical region. */ +int pvr2_ctrl_internal_set_value(struct pvr2_ctrl *cptr,int value) { + const struct pvr2_ctl_def *dptr; int ret; - if (ctl_id >= PVR2_CID_COUNT) return -EINVAL; - if (value < control_defs[ctl_id].min_value) return -EINVAL; - if (value > control_defs[ctl_id].max_value) return -EINVAL; - if (control_defs[ctl_id].set_func) { - ret = control_defs[ctl_id].set_func(hdw,ctl_id,value); - pvr2_i2c_core_check_stale(hdw); - pvr2_i2c_core_sync(hdw); + if (!cptr) return -EINVAL; + if (!cptr->is_valid) return -EINVAL; + dptr = cptr->ctl_def; + if (!dptr->is_valid) return -EINVAL; + if (value < dptr->min_value) return -EINVAL; + if (value > dptr->max_value) return -EINVAL; + if (dptr->set_func) { + ret = dptr->set_func(cptr,value); + pvr2_i2c_core_check_stale(cptr->hdw); + pvr2_i2c_core_sync(cptr->hdw); return ret; - } else if (control_defs[ctl_id].get_func) { + } else if (dptr->get_func) { /* If there's no "set" function yet there is still a "get" function, then treat this as a read-only value. */ return -EINVAL; } - if ((hdw->controls[ctl_id].value != value) || (ctlchg != 0)) { - hdw->controls[ctl_id].value = value; - hdw->controls[ctl_id].dirty = !0; + if ((cptr->value != value) || (ctlchg != 0)) { + cptr->value = value; + cptr->dirty = !0; } return 0; } -/* Set current value for given control - this is just stored; the hardware - isn't updated until the commit function is called. */ -int pvr2_hdw_set_ctl_value(struct pvr2_hdw *hdw,unsigned int ctl_id,int value) +/* Get the current value of a given control. This assumes that we are + already inside our critical region. */ +int pvr2_ctrl_internal_get_value(struct pvr2_ctrl *cptr) +{ + const struct pvr2_ctl_def *dptr; + if (!cptr) return 0; + if (!cptr->is_valid) return 0; + dptr = cptr->ctl_def; + if (!dptr->is_valid) return 0; + if (dptr->get_func) { + return dptr->get_func(cptr); + } + + return cptr->value; +} + + +/* Set the current value of the given control. */ +int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val) { int ret; - LOCK_TAKE(hdw->big_lock); do { - ret = pvr2_hdw_set_ctl_value_internal(hdw,ctl_id,value); - } while (0); LOCK_GIVE(hdw->big_lock); + if (!cptr) return -EINVAL; + LOCK_TAKE(cptr->hdw->big_lock); do { + ret = pvr2_ctrl_internal_set_value(cptr,val); + } while(0); LOCK_GIVE(cptr->hdw->big_lock); return ret; } -/* Retrieve string name for a given control value (returns a null pointer - for any invalid combinations). */ -const char *pvr2_hdw_get_ctl_value_name(struct pvr2_hdw *hdw, - unsigned int ctl_id, - int value) +/* Get the current value of the given control. */ +int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr) { - struct pvr2_ctl_def *cdef; - if (ctl_id >= PVR2_CID_COUNT) return 0; - cdef = control_defs + ctl_id; - if (! cdef->value_defs_ptr) return 0; - if (value >= cdef->value_defs_count) return 0; - return cdef->value_defs_ptr[value]; + int ret; + if (!cptr) return -EINVAL; + LOCK_TAKE(cptr->hdw->big_lock); do { + ret = pvr2_ctrl_internal_get_value(cptr); + } while(0); LOCK_GIVE(cptr->hdw->big_lock); + return ret; } -/* Retrieve string name for given control */ -const char *pvr2_hdw_get_ctl_name(struct pvr2_hdw *hdw,unsigned int ctl_id) +/* Return the type of the given control (int, enum, or bit mask). */ +int pvr2_ctrl_get_type(struct pvr2_ctrl *cptr) { - if (ctl_id >= PVR2_CID_COUNT) return 0; - return control_defs[ctl_id].name; + const struct pvr2_ctl_def *dptr; + if (!cptr) return PVR2_CTRL_TYPE_INVALID; + dptr = cptr->ctl_def; + if (dptr->mask_value) { + return PVR2_CTRL_TYPE_BITMASK; + } + if (dptr->value_defs_ptr) { + return PVR2_CTRL_TYPE_ENUM; + } + return PVR2_CTRL_TYPE_INT; +} + + +/* Return the minimum legal value for a given control. This command is + only relevant for int or enum types. */ +int pvr2_ctrl_get_min_value(struct pvr2_ctrl *cptr) +{ + const struct pvr2_ctl_def *dptr; + if (!cptr) return 0; + dptr = cptr->ctl_def; + return dptr->min_value; +} + + +/* Return the maximum legal value for a given control. This command is + only relevant for int or enum types. */ +int pvr2_ctrl_get_max_value(struct pvr2_ctrl *cptr) +{ + const struct pvr2_ctl_def *dptr; + if (!cptr) return 0; + dptr = cptr->ctl_def; + return dptr->max_value; +} + + +/* Return the default value for a given control. */ +int pvr2_ctrl_get_default_value(struct pvr2_ctrl *cptr) +{ + const struct pvr2_ctl_def *dptr; + if (!cptr) return 0; + dptr = cptr->ctl_def; + return dptr->default_value; +} + + +/* Return a mask of which bits are used within the bit mask of a given + control. This command is only relevant for bit mask types. */ +int pvr2_ctrl_get_mask_value(struct pvr2_ctrl *cptr) +{ + const struct pvr2_ctl_def *dptr; + if (!cptr) return 0; + dptr = cptr->ctl_def; + return dptr->mask_value; +} + + +/* Return true if this is a valid control. */ +int pvr2_ctrl_is_valid(struct pvr2_ctrl *cptr) +{ + if (!cptr) return 0; + return cptr->is_valid; +} + + +/* Return true if the control can be set (otherwise it may only be read, + assuming that it is valid). */ +int pvr2_ctrl_is_writeable(struct pvr2_ctrl *cptr) +{ + const struct pvr2_ctl_def *dptr; + if (!cptr) return 0; + dptr = cptr->ctl_def; + if (!dptr->is_valid) return 0; + if (dptr->set_func) return !0; + if (dptr->get_func) return 0; + return !0; +} + + +/* Return the control's name, or null if there isn't a name or the control + isn't otherwise valid. */ +const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr) +{ + const struct pvr2_ctl_def *dptr; + if (!cptr) return 0; + dptr = cptr->ctl_def; + return dptr->name; +} + + +/* Return the control's description, or null if there isn't a name or the + control isn't otherwise valid. */ +const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr) +{ + const struct pvr2_ctl_def *dptr; + if (!cptr) return 0; + dptr = cptr->ctl_def; + return dptr->desc; +} + + +/* Return the name for an enumeration value or bit mask position for the + given control. If the control is not an enumeration or bit mask type, + then return null. */ +const char *pvr2_ctrl_get_value_name(struct pvr2_ctrl *cptr,int val) +{ + int msk,idx; + const struct pvr2_ctl_def *dptr; + if (!cptr) return 0; + dptr = cptr->ctl_def; + if (dptr->mask_value) { + for (idx = 0, msk = 1; + (idx < dptr->value_defs_count) && msk; + idx++, msk <<= 1) { + if (val & msk) { + return dptr->value_defs_ptr[idx]; + } + } + } else { + val -= dptr->min_value; + if (val < 0) return 0; + if (val >= dptr->value_defs_count) return 0; + return dptr->value_defs_ptr[val]; + } + return 0; } @@ -1560,6 +2193,8 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) unsigned long saved_subsys_mask = hdw->subsys_enabled_mask; unsigned long stale_subsys_mask = 0; unsigned int idx; + const struct pvr2_ctl_def *dptr; + struct pvr2_ctrl *cptr; int value; const char *ctl_name; const char *ctl_value; @@ -1595,17 +2230,18 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) } } - for (idx = 0; idx < PVR2_CID_COUNT; idx++) { - if (!hdw->controls[idx].dirty) continue; + for (idx = 0; idx < CTRL_COUNT; idx++) { + cptr = hdw->controls + idx; + if (!cptr->dirty) continue; if (!commit_flag) { commit_flag = !0; } - value = hdw->controls[idx].value; - ctl_name = control_defs[idx].name; - if (control_defs[idx].value_defs_ptr) { - if (value < control_defs[idx].value_defs_count) { - ctl_value = - control_defs[idx].value_defs_ptr[value]; + value = cptr->value; + dptr = cptr->ctl_def; + ctl_name = dptr->name; + if (dptr->value_defs_ptr) { + if (value < dptr->value_defs_count) { + ctl_value = dptr->value_defs_ptr[value]; } else { ctl_value = "<out of range>"; } @@ -1625,16 +2261,13 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) /* When video standard changes, reset the hres and vres values - but if the user has pending changes there, then let the changes take priority. */ - if (hdw->controls[PVR2_CID_VIDEOSTANDARD].dirty) { + if (hdw->controls[PVR2_CID_STDCUR].dirty) { /* Rewrite the vertical resolution to be appropriate to the video standard that has been selected. */ - int nvres = hdw->controls[PVR2_CID_VRES].value; - switch (hdw->controls[PVR2_CID_VIDEOSTANDARD].value) { - case PVR2_CVAL_VIDEOSTANDARD_NTSC_M: - case PVR2_CVAL_VIDEOSTANDARD_PAL_M: + int nvres; + if (hdw->video_std_cur & V4L2_STD_525_60) { nvres = 480; - break; - default: + } else { nvres = 576; } if (nvres != hdw->controls[PVR2_CID_VRES].value) { @@ -1647,7 +2280,7 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) } } - if (hdw->controls[PVR2_CID_VIDEOSTANDARD].dirty || + if (hdw->controls[PVR2_CID_STDCUR].dirty || hdw->controls[PVR2_CID_VRES].dirty || hdw->controls[PVR2_CID_HRES].dirty || hdw->controls[PVR2_CID_INTERLACE].dirty || @@ -1671,8 +2304,9 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) the client drivers in order to keep everything in sync */ pvr2_i2c_core_check_stale(hdw); - for (idx = 0; idx < PVR2_CID_COUNT; idx++) { - hdw->controls[idx].dirty = 0; + for (idx = 0; idx < CTRL_COUNT; idx++) { + cptr = hdw->controls + idx; + cptr->dirty = 0; } /* Now execute i2c core update */ @@ -1729,14 +2363,6 @@ void pvr2_hdw_poll_trigger(struct pvr2_hdw *hdw) } -/* Find out how many controls there are. Legal ids are numbered from 1 - through this value. */ -unsigned int pvr2_hdw_get_ctl_count(struct pvr2_hdw *hdw) -{ - return PVR2_CID_COUNT; -} - - /* Return name for this driver instance */ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw) { @@ -1772,36 +2398,36 @@ unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw) } -static int pvr2_ctl_get_subsys_mask(struct pvr2_hdw *hdw,int ctl_id) +static int pvr2_ctl_get_subsys_mask(struct pvr2_ctrl *cptr) { - return hdw->subsys_enabled_mask; + return cptr->hdw->subsys_enabled_mask; } -static int pvr2_ctl_set_subsys_mask(struct pvr2_hdw *hdw,int ctl_id,int val) +static int pvr2_ctl_set_subsys_mask(struct pvr2_ctrl *cptr,int val) { - pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,val); + pvr2_hdw_subsys_bit_chg_no_lock(cptr->hdw,~0,val); return 0; } -static int pvr2_ctl_get_subsys_stream_mask(struct pvr2_hdw *hdw,int ctl_id) +static int pvr2_ctl_get_subsys_stream_mask(struct pvr2_ctrl *cptr) { - return hdw->subsys_stream_mask; + return cptr->hdw->subsys_stream_mask; } -static int pvr2_ctl_set_subsys_stream_mask(struct pvr2_hdw *hdw,int ctl_id, +static int pvr2_ctl_set_subsys_stream_mask(struct pvr2_ctrl *cptr, int val) { - pvr2_hdw_subsys_stream_bit_chg_no_lock(hdw,~0,val); + pvr2_hdw_subsys_stream_bit_chg_no_lock(cptr->hdw,~0,val); return 0; } -static int pvr2_ctl_get_hsm(struct pvr2_hdw *hdw,int ctl_id) +static int pvr2_ctl_get_hsm(struct pvr2_ctrl *cptr) { - int result = pvr2_hdw_is_hsm(hdw); + int result = pvr2_hdw_is_hsm(cptr->hdw); if (result < 0) return PVR2_CVAL_HSM_FAIL; if (result) return PVR2_CVAL_HSM_HIGH; return PVR2_CVAL_HSM_FULL; @@ -1823,10 +2449,10 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) } -static int pvr2_ctl_get_signal(struct pvr2_hdw *hdw,int ctl_id) +static int pvr2_ctl_get_signal(struct pvr2_ctrl *cptr) { - return ((pvr2_hdw_get_signal_status_internal(hdw) & PVR2_SIGNAL_OK) ? - 1 : 0); + return ((pvr2_hdw_get_signal_status_internal(cptr->hdw) & + PVR2_SIGNAL_OK) ? 1 : 0); } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h index aa6d9029a..4101f4097 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -21,89 +21,37 @@ #ifndef __PVRUSB2_HDW_H #define __PVRUSB2_HDW_H +#include "compat.h" #include <linux/usb.h> +#include <linux/videodev2.h> #include "pvrusb2-io.h" -/* Definition of state variables that we can inspect & change. Numbers are - assigned from zero counting up with no gaps. */ -#define PVR2_CID_BRIGHTNESS 0 -#define PVR2_CID_CONTRAST 1 -#define PVR2_CID_SATURATION 2 -#define PVR2_CID_HUE 3 -#define PVR2_CID_VOLUME 4 -#define PVR2_CID_BALANCE 5 -#define PVR2_CID_BASS 6 -#define PVR2_CID_TREBLE 7 -#define PVR2_CID_MUTE 8 -#define PVR2_CID_SRATE 9 -#define PVR2_CID_AUDIOBITRATE 10 -#define PVR2_CID_AUDIOCRC 11 -#define PVR2_CID_AUDIOEMPHASIS 12 -#define PVR2_CID_VBR 13 -#define PVR2_CID_AVERAGEVIDEOBITRATE 14 -#define PVR2_CID_PEAKVIDEOBITRATE 15 -#define PVR2_CID_VIDEOSTANDARD 16 -#define PVR2_CID_INPUT 17 -#define PVR2_CID_AUDIOMODE 18 -#define PVR2_CID_FREQUENCY 19 // Units of Hz -#define PVR2_CID_HRES 20 -#define PVR2_CID_VRES 21 -#define PVR2_CID_INTERLACE 22 -#define PVR2_CID_AUDIOLAYER 23 -#define PVR2_CID_CHANNEL 24 -#define PVR2_CID_CHANPROG_ID 25 -#define PVR2_CID_CHANPROG_FREQ 26 -#define PVR2_CID_SIGNAL_PRESENT 27 -#define PVR2_CID_STREAMING_ENABLED 28 -#define PVR2_CID_HSM 29 -#define PVR2_CID_SUBSYS_MASK 30 -#define PVR2_CID_SUBSYS_STREAM_MASK 31 - -/* Number of state variables */ -#define PVR2_CID_COUNT 32 - -/* Legal values for the SRATE state variable */ -#define PVR2_CVAL_SRATE_48 0 -#define PVR2_CVAL_SRATE_44_1 1 -#define PVR2_CVAL_SRATE_MIN PVR2_CVAL_SRATE_48 -#define PVR2_CVAL_SRATE_MAX PVR2_CVAL_SRATE_44_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 -#define PVR2_CVAL_AUDIOBITRATE_MIN PVR2_CVAL_AUDIOBITRATE_384 -#define PVR2_CVAL_AUDIOBITRATE_MAX PVR2_CVAL_AUDIOBITRATE_VBR - -/* 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 -#define PVR2_CVAL_AUDIOEMPHASIS_MIN PVR2_CVAL_AUDIOEMPHASIS_NONE -#define PVR2_CVAL_AUDIOEMPHASIS_MAX PVR2_CVAL_AUDIOEMPHASIS_CCITT - -/* Legal values for the VIDEOSTANDARD state variable */ -#define PVR2_CVAL_VIDEOSTANDARD_NTSC_M 0 -#define PVR2_CVAL_VIDEOSTANDARD_PAL_BG 1 -#define PVR2_CVAL_VIDEOSTANDARD_PAL_I 2 -#define PVR2_CVAL_VIDEOSTANDARD_PAL_DK 3 -#define PVR2_CVAL_VIDEOSTANDARD_PAL_M 4 -#define PVR2_CVAL_VIDEOSTANDARD_SECAM_L 5 - -#define PVR2_CVAL_VIDEOSTANDARD_MIN PVR2_CVAL_VIDEOSTANDARD_NTSC_M -#define PVR2_CVAL_VIDEOSTANDARD_MAX PVR2_CVAL_VIDEOSTANDARD_SECAM_L +#define PVR2_CTRL_TYPE_INVALID 0 +#define PVR2_CTRL_TYPE_ENUM 1 +#define PVR2_CTRL_TYPE_INT 2 +#define PVR2_CTRL_TYPE_BITMASK 3 + +/* Private V4L2-compatible controls available in this driver */ +#define V4L2_CID_PVR_SRATE (V4L2_CID_PRIVATE_BASE) +#define V4L2_CID_PVR_AUDIOBITRATE (V4L2_CID_PRIVATE_BASE+1) +#define V4L2_CID_PVR_AUDIOCRC (V4L2_CID_PRIVATE_BASE+2) +#define V4L2_CID_PVR_AUDIOEMPHASIS (V4L2_CID_PRIVATE_BASE+3) +#define V4L2_CID_PVR_VBR (V4L2_CID_PRIVATE_BASE+4) +#define V4L2_CID_PVR_VIDEOBITRATE (V4L2_CID_PRIVATE_BASE+5) +#define V4L2_CID_PVR_VIDEOPEAK (V4L2_CID_PRIVATE_BASE+6) +#define V4L2_CID_PVR_VIDEOSTANDARD (V4L2_CID_PRIVATE_BASE+7) + +/* Deliberate gap for CIDs we don't want apps to discover */ +#define V4L2_CID_PVR_GAP (V4L2_CID_PRIVATE_BASE+8) + +/* Additional explicit controls needed by V4L2 ioctl implementation */ +#define V4L2_CID_PVR_STDCUR (V4L2_CID_PVR_GAP+1) +#define V4L2_CID_PVR_INPUT (V4L2_CID_PVR_GAP+2) +#define V4L2_CID_PVR_AUDIOMODE (V4L2_CID_PVR_GAP+3) +#define V4L2_CID_PVR_FREQUENCY (V4L2_CID_PVR_GAP+4) +#define V4L2_CID_PVR_HRES (V4L2_CID_PVR_GAP+5) +#define V4L2_CID_PVR_VRES (V4L2_CID_PVR_GAP+6) +#define V4L2_CID_PVR_INTERLACE (V4L2_CID_PVR_GAP+7) /* Legal values for the INPUT state variable */ #define PVR2_CVAL_INPUT_TV 0 @@ -113,27 +61,11 @@ #define PVR2_CVAL_INPUT_MIN PVR2_CVAL_INPUT_TV #define PVR2_CVAL_INPUT_MAX PVR2_CVAL_INPUT_RADIO -/* Legal values for the AUDIOMODE state variable */ -#define PVR2_CVAL_AUDIOMODE_MONO 0 -#define PVR2_CVAL_AUDIOMODE_STEREO 1 -#define PVR2_CVAL_AUDIOMODE_SAP 2 -#define PVR2_CVAL_AUDIOMODE_LANG1 3 -#define PVR2_CVAL_AUDIOMODE_LANG2 4 -#define PVR2_CVAL_AUDIOMODE_LANG1_LANG2 5 -#define PVR2_CVAL_AUDIOMODE_MIN PVR2_CVAL_AUDIOMODE_MONO -#define PVR2_CVAL_AUDIOMODE_MAX PVR2_CVAL_AUDIOMODE_LANG1_LANG2 - /* Values that pvr2_hdw_get_signal_status() returns */ #define PVR2_SIGNAL_OK 0x0001 #define PVR2_SIGNAL_STEREO 0x0002 #define PVR2_SIGNAL_SAP 0x0004 -/* 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_CVAL_HSM_MIN PVR2_CVAL_HSM_FAIL -#define PVR2_CVAL_HSM_MAX PVR2_CVAL_HSM_HIGH /* Subsystem definitions - these are various pieces that can be independently stopped / started. Usually you don't want to mess with @@ -167,6 +99,8 @@ const char *pvr2_config_get_name(enum pvr2_config); struct pvr2_hdw; +struct pvr2_ctrl; + /* Create and return a structure for interacting with the underlying hardware */ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, @@ -215,37 +149,69 @@ unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *); /* Called when hardware has been unplugged */ void pvr2_hdw_disconnect(struct pvr2_hdw *); -/* Retrieve current value for a given control */ -int pvr2_hdw_get_ctl_value(struct pvr2_hdw *,unsigned int ctl_id); +/* Get the number of defined controls */ +unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *); + +/* Retrieve a control handle given its index (0..count-1) */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *,unsigned int); + +/* Retrieve a control handle given its well known ID */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl(struct pvr2_hdw *,unsigned int ctl_id); + +/* Set the current value of the given control. */ +int pvr2_ctrl_set_value(struct pvr2_ctrl *,int val); + +/* Get the current value of the given control. */ +int pvr2_ctrl_get_value(struct pvr2_ctrl *); + +/* Return the type of the given control (int, enum, or bit mask). */ +int pvr2_ctrl_get_type(struct pvr2_ctrl *); -/* Return true if control is writable */ -int pvr2_hdw_get_ctl_rw(struct pvr2_hdw *,unsigned int ctl_id); +/* Return the minimum legal value for a given control. This command is + only relevant for int or enum types. */ +int pvr2_ctrl_get_min_value(struct pvr2_ctrl *); -/* Retrieve legal minimum value for a given control */ -int pvr2_hdw_get_ctl_min_value(struct pvr2_hdw *,unsigned int ctl_id); +/* Return the maximum legal value for a given control. This command is + only relevant for int or enum types. */ +int pvr2_ctrl_get_max_value(struct pvr2_ctrl *); -/* Retrieve legal maximum value for a given control */ -int pvr2_hdw_get_ctl_max_value(struct pvr2_hdw *,unsigned int ctl_id); +/* Return a mask of which bits are used within the bit mask of a given + control. This command is only relevant for bit mask types. */ +int pvr2_ctrl_get_mask_value(struct pvr2_ctrl *); -/* Set current value for given control - this is just stored; the hardware - isn't updated until the commit function is called. */ -int pvr2_hdw_set_ctl_value(struct pvr2_hdw *,unsigned int ctl_id,int value); +/* Return the default value for a given control. */ +int pvr2_ctrl_get_default_value(struct pvr2_ctrl *); -/* Retrieve string name for given control */ -const char *pvr2_hdw_get_ctl_name(struct pvr2_hdw *,unsigned int ctl_id); +/* Return true if this is a valid control. */ +int pvr2_ctrl_is_valid(struct pvr2_ctrl *); -/* Retrieve string name for a given control value (returns a null pointer - for any invalid combinations). */ -const char *pvr2_hdw_get_ctl_value_name(struct pvr2_hdw *, - unsigned int ctl_id,int value); +/* Return true if the control can be set (otherwise it may only be read, + assuming that it is valid). */ +int pvr2_ctrl_is_writeable(struct pvr2_ctrl *); + +/* Return the control's name, or null if there isn't a name or the control + isn't otherwise valid. */ +const char *pvr2_ctrl_get_name(struct pvr2_ctrl *); + +/* Return the control's description, or null if there isn't a name or the + control isn't otherwise valid. */ +const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *); + +/* Return the name for an enumeration value or bit mask position for the + given control. If the control is not an enumeration or bit mask type, + then return null. */ +const char *pvr2_ctrl_get_value_name(struct pvr2_ctrl *,int val); + +/* Return the number of support standard groups */ +unsigned int pvr2_hdw_get_stdenum_count(struct pvr2_hdw *); + +/* Return a pointer to a v4l2 standard descriptor for a given group */ +const struct v4l2_standard *pvr2_hdw_get_stdenum_value(struct pvr2_hdw *, + unsigned int idx); /* Commit all control changes made up to this point */ int pvr2_hdw_commit_ctl(struct pvr2_hdw *); -/* Find out how many controls there are. Legal ids are numbered from 0 - through this value - 1. */ -unsigned int pvr2_hdw_get_ctl_count(struct pvr2_hdw *); - /* Return name for this driver instance */ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c index fc9d76792..89d0da053 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c @@ -28,8 +28,10 @@ #include "pvrusb2-tuner.h" #include "pvrusb2-demod.h" #include "pvrusb2-video-v4l.h" +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX #include "pvrusb2-cx2584x-v4l.h" #include "pvrusb2-wm8775.h" +#endif #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) @@ -71,6 +73,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) return; } } +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX if (id == I2C_DRIVERID_CX25840) { if (pvr2_i2c_cx2584x_v4l_setup(hdw,cp)) { return; @@ -81,6 +84,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) return; } } +#endif if (id == I2C_DRIVERID_SAA711X) { if (pvr2_i2c_decoder_v4l_setup(hdw,cp)) { return; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c index 000c26911..b3d2ce926 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c @@ -24,43 +24,23 @@ #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include <linux/videodev.h> +#include <linux/videodev2.h> static void set_standard(struct pvr2_hdw *hdw) { - int cvstd = hdw->controls[PVR2_CID_VIDEOSTANDARD].value; v4l2_std_id vs; + vs = hdw->controls[PVR2_CID_STDCUR].value; pvr2_trace(PVR2_TRACE_CHIPS, - "i2c v4l2 set_standard(%d)",cvstd); - - switch (cvstd) { - default: - case PVR2_CVAL_VIDEOSTANDARD_NTSC_M: - vs = V4L2_STD_NTSC_M; - break; - case PVR2_CVAL_VIDEOSTANDARD_SECAM_L: - vs = V4L2_STD_SECAM; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_BG: - vs = V4L2_STD_PAL_BG; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_I: - vs = V4L2_STD_PAL_I; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_DK: - vs = V4L2_STD_PAL_DK; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_M: - vs = V4L2_STD_PAL_M; - break; - } + "i2c v4l2 set_standard(0x%llx)",(__u64)vs); + pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); } static int check_standard(struct pvr2_hdw *hdw) { - return hdw->controls[PVR2_CID_VIDEOSTANDARD].dirty != 0; + return hdw->controls[PVR2_CID_STDCUR].dirty != 0; } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 2f7946195..9a96273f2 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -262,18 +262,29 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap, done: if (pvrusb2_debug & PVR2_TRACE_I2C_TRAF) { - unsigned int idx; + unsigned int idx,offs,cnt; for (idx = 0; idx < num; idx++) { + cnt = msgs[idx].len; printk(KERN_INFO "pvrusb2 i2c xfer %u/%u:" " addr=0x%x len=%d %s%s", idx+1,num, msgs[idx].addr, - msgs[idx].len, + cnt, (msgs[idx].flags & I2C_M_RD ? "read" : "write"), (msgs[idx].flags & I2C_M_NOSTART ? " nostart" : "")); + if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) { + if (cnt > 8) cnt = 8; + printk(" ["); + for (offs = 0; offs < (cnt>8?8:cnt); offs++) { + if (offs) printk(" "); + printk("%02x",msgs[idx].buf[offs]); + } + if (offs < cnt) printk(" ..."); + printk("]"); + } if (idx+1 == num) { printk(" result=%d",ret); } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-main.c b/linux/drivers/media/video/pvrusb2/pvrusb2-main.c index c070fc195..40fb6ae41 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-main.c @@ -35,7 +35,9 @@ #include "pvrusb2-context.h" #include "pvrusb2-debug.h" #include "pvrusb2-v4l2.h" +#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS #include "pvrusb2-sysfs.h" +#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ #define DRIVER_AUTHOR "Mike Isely <isely@pobox.com>" #define DRIVER_DESC "Hauppauge WinTV-PVR-USB2 MPEG2 Encoder/Tuner" @@ -60,13 +62,17 @@ int pvrusb2_debug = DEFAULT_DEBUG_MASK; module_param_named(debug,pvrusb2_debug,int,S_IRUGO|S_IWUSR); MODULE_PARM_DESC(debug, "Debug trace mask"); +#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS static struct pvr2_sysfs_class *class_ptr = 0; +#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ static void pvr_setup_attach(struct pvr2_context *pvr) { /* Create association with v4l layer */ pvr2_v4l2_create(pvr); +#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS pvr2_sysfs_create(pvr,class_ptr); +#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ } static int pvr_probe(struct usb_interface *intf, @@ -138,7 +144,9 @@ static int __init pvr_init(void) request_module("tda9887"); request_module("wm8775"); +#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS class_ptr = pvr2_sysfs_class_create(); +#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ ret = usb_register(&pvr_driver); @@ -155,7 +163,9 @@ static void __exit pvr_exit(void) pvr2_trace(PVR2_TRACE_INIT,"pvr_exit"); +#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS pvr2_sysfs_class_destroy(class_ptr); +#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ usb_deregister(&pvr_driver); } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index f82fd643c..053c0b24c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -26,49 +26,18 @@ #include "pvrusb2-sysfs.h" #include "pvrusb2-hdw.h" #include "pvrusb2-debug.h" +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC #include "pvrusb2-debugifc.h" +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ #define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__) -static char *item_names[PVR2_CID_COUNT] = { - [PVR2_CID_BRIGHTNESS] = "ctl_brightness", - [PVR2_CID_CONTRAST] = "ctl_contrast", - [PVR2_CID_SATURATION] = "ctl_saturation", - [PVR2_CID_HUE] = "ctl_hue", - [PVR2_CID_VOLUME] = "ctl_volume", - [PVR2_CID_BALANCE] = "ctl_balance", - [PVR2_CID_BASS] = "ctl_bass", - [PVR2_CID_TREBLE] = "ctl_treble", - [PVR2_CID_MUTE] = "ctl_mute", - [PVR2_CID_SRATE] = "ctl_srate", - [PVR2_CID_AUDIOBITRATE] = "ctl_audio_bitrate", - [PVR2_CID_AUDIOCRC] = "ctl_audio_crc", - [PVR2_CID_AUDIOEMPHASIS] = "ctl_audio_emphasis", - [PVR2_CID_VBR] = "ctl_vbr", - [PVR2_CID_AVERAGEVIDEOBITRATE] = "ctl_video_average_bitrate", - [PVR2_CID_PEAKVIDEOBITRATE] = "ctl_video_peak_bitrate", - [PVR2_CID_VIDEOSTANDARD] = "ctl_video_standard", - [PVR2_CID_INPUT] = "ctl_input", - [PVR2_CID_AUDIOMODE] = "ctl_audio_mode", - [PVR2_CID_FREQUENCY] = "ctl_frequency", - [PVR2_CID_HRES] = "ctl_resolution_hor", - [PVR2_CID_VRES] = "ctl_resolution_ver", - [PVR2_CID_INTERLACE] = "ctl_interlace", - [PVR2_CID_AUDIOLAYER] = "ctl_audio_layer", - [PVR2_CID_CHANNEL] = "ctl_channel", - [PVR2_CID_CHANPROG_ID] = "ctl_freq_table_channel", - [PVR2_CID_CHANPROG_FREQ] = "ctl_freq_table_value", - [PVR2_CID_SIGNAL_PRESENT] = "ctl_signal_present", - [PVR2_CID_STREAMING_ENABLED] = "ctl_streaming_enabled", - [PVR2_CID_HSM] = "ctl_usb_speed", - [PVR2_CID_SUBSYS_MASK] = "ctl_debug_subsys_mask", - [PVR2_CID_SUBSYS_STREAM_MASK] = "ctl_debug_subsys_stream_mask", -}; - struct pvr2_sysfs { struct pvr2_channel channel; struct class_device *class_dev; +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC struct pvr2_sysfs_debugifc *debugifc; +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ struct pvr2_sysfs_ctl_item *item_first; struct pvr2_sysfs_ctl_item *item_last; struct sysfs_ops kops; @@ -77,10 +46,12 @@ struct pvr2_sysfs { struct class_device_attribute attr_unit_number; }; +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC struct pvr2_sysfs_debugifc { struct class_device_attribute attr_debugcmd; struct class_device_attribute attr_debuginfo; }; +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ struct pvr2_sysfs_ctl_item { struct class_device_attribute attr_name; @@ -88,11 +59,12 @@ struct pvr2_sysfs_ctl_item { struct class_device_attribute attr_max; struct class_device_attribute attr_enum; struct class_device_attribute attr_val; - int attr_id; + struct pvr2_ctrl *cptr; struct pvr2_sysfs *chptr; struct pvr2_sysfs_ctl_item *item_next; struct attribute *attr_gen[5]; struct attribute_group grp; + char name[80]; }; struct pvr2_sysfs_class { @@ -101,13 +73,16 @@ struct pvr2_sysfs_class { static ssize_t show_name(int id,struct class_device *class_dev,char *buf) { + struct pvr2_ctrl *cptr; struct pvr2_sysfs *sfp; const char *name; sfp = (struct pvr2_sysfs *)class_dev->class_data; if (!sfp) return -EINVAL; - name = pvr2_hdw_get_ctl_name(sfp->channel.hdw,id); + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; + name = pvr2_ctrl_get_desc(cptr); pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",sfp,id,name); if (!name) return -EINVAL; @@ -117,13 +92,15 @@ static ssize_t show_name(int id,struct class_device *class_dev,char *buf) static ssize_t show_min(int id,struct class_device *class_dev,char *buf) { + struct pvr2_ctrl *cptr; struct pvr2_sysfs *sfp; int val; sfp = (struct pvr2_sysfs *)class_dev->class_data; if (!sfp) return -EINVAL; - val = pvr2_hdw_get_ctl_min_value(sfp->channel.hdw,id); - + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; + val = pvr2_ctrl_get_min_value(cptr); pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %d",sfp,id,val); return scnprintf(buf,PAGE_SIZE,"%d\n",val); @@ -131,12 +108,15 @@ static ssize_t show_min(int id,struct class_device *class_dev,char *buf) static ssize_t show_max(int id,struct class_device *class_dev,char *buf) { + struct pvr2_ctrl *cptr; struct pvr2_sysfs *sfp; int val; sfp = (struct pvr2_sysfs *)class_dev->class_data; if (!sfp) return -EINVAL; - val = pvr2_hdw_get_ctl_max_value(sfp->channel.hdw,id); + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; + val = pvr2_ctrl_get_max_value(cptr); pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %d",sfp,id,val); @@ -145,12 +125,15 @@ static ssize_t show_max(int id,struct class_device *class_dev,char *buf) static ssize_t show_val_int(int id,struct class_device *class_dev,char *buf) { + struct pvr2_ctrl *cptr; struct pvr2_sysfs *sfp; int val; sfp = (struct pvr2_sysfs *)class_dev->class_data; if (!sfp) return -EINVAL; - val = pvr2_hdw_get_ctl_value(sfp->channel.hdw,id); + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; + val = pvr2_ctrl_get_value(cptr); pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_int(cid=%d) is %d", sfp,id,val); @@ -160,15 +143,18 @@ static ssize_t show_val_int(int id,struct class_device *class_dev,char *buf) static ssize_t show_val_enum(int id,struct class_device *class_dev,char *buf) { + struct pvr2_ctrl *cptr; struct pvr2_sysfs *sfp; int val; const char *name; sfp = (struct pvr2_sysfs *)class_dev->class_data; if (!sfp) return -EINVAL; - val = pvr2_hdw_get_ctl_value(sfp->channel.hdw,id); + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; - name = pvr2_hdw_get_ctl_value_name(sfp->channel.hdw,id,val); + val = pvr2_ctrl_get_value(cptr); + name = pvr2_ctrl_get_value_name(cptr,val); pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_enum(cid=%d) is %s (%d)", sfp,id,name,val); @@ -178,6 +164,7 @@ static ssize_t show_val_enum(int id,struct class_device *class_dev,char *buf) static ssize_t show_enum(int id,struct class_device *class_dev,char *buf) { + struct pvr2_ctrl *cptr; struct pvr2_sysfs *sfp; int minval,maxval,val; const char *name; @@ -185,10 +172,12 @@ static ssize_t show_enum(int id,struct class_device *class_dev,char *buf) sfp = (struct pvr2_sysfs *)class_dev->class_data; if (!sfp) return -EINVAL; - minval = pvr2_hdw_get_ctl_min_value(sfp->channel.hdw,id); - maxval = pvr2_hdw_get_ctl_max_value(sfp->channel.hdw,id); + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; + minval = pvr2_ctrl_get_min_value(cptr); + maxval = pvr2_ctrl_get_max_value(cptr); for (val = minval; val <= maxval; val++) { - name = pvr2_hdw_get_ctl_value_name(sfp->channel.hdw,id,val); + name = pvr2_ctrl_get_value_name(cptr,val); cnt += scnprintf(buf+cnt,PAGE_SIZE-cnt,"%s\n",name); } pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp,id); @@ -198,6 +187,7 @@ static ssize_t show_enum(int id,struct class_device *class_dev,char *buf) static int store_val_any(int id,struct pvr2_sysfs *sfp, const char *buf,unsigned int count) { + struct pvr2_ctrl *cptr; int val,minval,maxval; int ch,ret; const char *nv; @@ -217,11 +207,14 @@ static int store_val_any(int id,struct pvr2_sysfs *sfp, count--; } + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; + /* Is this an enum? Look for a string value */ - minval = pvr2_hdw_get_ctl_min_value(sfp->channel.hdw,id); - maxval = pvr2_hdw_get_ctl_max_value(sfp->channel.hdw,id); + minval = pvr2_ctrl_get_min_value(cptr); + maxval = pvr2_ctrl_get_max_value(cptr); for (val = minval; val <= maxval; val++) { - nv = pvr2_hdw_get_ctl_value_name(sfp->channel.hdw,id,val); + nv = pvr2_ctrl_get_value_name(cptr,val); if ((!nv) && (val == minval)) break; /* Not an enum */ pvr2_sysfs_trace("pvr2_sysfs(%p) trying ctl_id %d val %d", sfp,id,val); @@ -246,7 +239,7 @@ static int store_val_any(int id,struct pvr2_sysfs *sfp, pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_any(cid=%d)" " is enum %s", sfp,id,nv); - ret = pvr2_hdw_set_ctl_value(sfp->channel.hdw,id,val); + ret = pvr2_ctrl_set_value(cptr,val); pvr2_hdw_commit_ctl(sfp->channel.hdw); return 0; } @@ -284,7 +277,7 @@ static int store_val_any(int id,struct pvr2_sysfs *sfp, " int is %d", sfp,id,val); - ret = pvr2_hdw_set_ctl_value(sfp->channel.hdw,id,val); + ret = pvr2_ctrl_set_value(cptr,val); pvr2_hdw_commit_ctl(sfp->channel.hdw); return ret; } @@ -395,6 +388,8 @@ CREATE_BATCH(28) CREATE_BATCH(29) CREATE_BATCH(30) CREATE_BATCH(31) +CREATE_BATCH(32) +CREATE_BATCH(33) struct pvr2_sysfs_func_set { ssize_t (*show_name)(struct class_device *,char *); @@ -454,6 +449,8 @@ static struct pvr2_sysfs_func_set funcs[] = { INIT_BATCH(29), INIT_BATCH(30), INIT_BATCH(31), + INIT_BATCH(32), + INIT_BATCH(33), }; @@ -461,19 +458,23 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) { struct pvr2_sysfs_ctl_item *cip; struct pvr2_sysfs_func_set *fp; + struct pvr2_ctrl *cptr; + unsigned int cnt; if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) { return; } fp = funcs + ctl_id; + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id); + if (!cptr) return; cip = kmalloc(sizeof(*cip),GFP_KERNEL); if (!cip) return; memset(cip,0,sizeof(*cip)); pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip); - cip->attr_id = ctl_id; + cip->cptr = cptr; cip->chptr = sfp; cip->item_next = 0; @@ -508,15 +509,13 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) cip->attr_enum.attr.mode = S_IRUGO; cip->attr_enum.show = fp->show_enum; - if (pvr2_hdw_get_ctl_rw(sfp->channel.hdw,ctl_id)) { + if (pvr2_ctrl_is_writeable(cptr)) { cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP; } cip->attr_gen[0] = &cip->attr_name.attr; cip->attr_gen[1] = &cip->attr_val.attr; - if (pvr2_hdw_get_ctl_value_name( - sfp->channel.hdw,ctl_id, - pvr2_hdw_get_ctl_min_value(sfp->channel.hdw,ctl_id))) { + if (pvr2_ctrl_get_type(cptr) == PVR2_CTRL_TYPE_ENUM) { // Control is an enumeration cip->attr_gen[2] = &cip->attr_enum.attr; cip->attr_val.show = fp->show_val_enum; @@ -529,12 +528,16 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) cip->attr_gen[3] = &cip->attr_max.attr; } - cip->grp.name = item_names[ctl_id]; + cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s", + pvr2_ctrl_get_name(cptr)); + cip->name[cnt] = 0; + cip->grp.name = cip->name; cip->grp.attrs = cip->attr_gen; sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); } +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC static ssize_t debuginfo_show(struct class_device *,char *); static ssize_t debugcmd_show(struct class_device *,char *); static ssize_t debugcmd_store(struct class_device *,const char *,size_t count); @@ -569,16 +572,15 @@ static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp) kfree(sfp->debugifc); sfp->debugifc = 0; } +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ static void pvr2_sysfs_add_controls(struct pvr2_sysfs *sfp) { - unsigned int ctl_id; - - for (ctl_id = 0; - ctl_id < (sizeof(item_names)/sizeof(item_names[0])); ctl_id++) { - if (!item_names[ctl_id]) continue; - pvr2_sysfs_add_control(sfp,ctl_id); + unsigned int idx,cnt; + cnt = pvr2_hdw_get_ctrl_count(sfp->channel.hdw); + for (idx = 0; idx < cnt; idx++) { + pvr2_sysfs_add_control(sfp,idx); } } @@ -614,7 +616,9 @@ static void pvr2_sysfs_release(struct class_device *class_dev) static void class_dev_destroy(struct pvr2_sysfs *sfp) { if (!sfp->class_dev) return; +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC pvr2_sysfs_tear_down_debugifc(sfp); +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ pvr2_sysfs_tear_down_controls(sfp); class_device_remove_file(sfp->class_dev,&sfp->attr_v4l_minor_number); class_device_remove_file(sfp->class_dev,&sfp->attr_unit_number); @@ -690,7 +694,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp, class_device_create_file(sfp->class_dev,&sfp->attr_unit_number); pvr2_sysfs_add_controls(sfp); +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC pvr2_sysfs_add_debugifc(sfp); +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ } @@ -761,6 +767,7 @@ void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp) } +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC static ssize_t debuginfo_show(struct class_device *class_dev,char *buf) { struct pvr2_sysfs *sfp; @@ -793,6 +800,7 @@ static ssize_t debugcmd_store(struct class_device *class_dev, if (ret < 0) return ret; return count; } +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ /* diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index dd207fae4..fe7045e8f 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -80,22 +80,6 @@ static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1}; module_param_array(video_nr, int, NULL, 0444); MODULE_PARM_DESC(video_nr, "Offset for device's minor"); -#define V4L2_CID_PVR_SRATE (V4L2_CID_PRIVATE_BASE) -#define V4L2_CID_PVR_AUDIOBITRATE (V4L2_CID_PRIVATE_BASE+1) -#define V4L2_CID_PVR_AUDIOCRC (V4L2_CID_PRIVATE_BASE+2) -#define V4L2_CID_PVR_AUDIOEMPHASIS (V4L2_CID_PRIVATE_BASE+3) -#define V4L2_CID_PVR_VBR (V4L2_CID_PRIVATE_BASE+4) -#define V4L2_CID_PVR_VIDEOBITRATE (V4L2_CID_PRIVATE_BASE+5) -#define V4L2_CID_PVR_VIDEOPEAK (V4L2_CID_PRIVATE_BASE+6) -#define V4L2_CID_PVR_VIDEOSTANDARD (V4L2_CID_PRIVATE_BASE+7) -#define V4L2_CID_PVR_INPUT (V4L2_CID_PRIVATE_BASE+8) -#define V4L2_CID_PVR_AUDIOMODE (V4L2_CID_PRIVATE_BASE+9) -#define V4L2_CID_PVR_FREQUENCY (V4L2_CID_PRIVATE_BASE+10) -#define V4L2_CID_PVR_HRES (V4L2_CID_PRIVATE_BASE+11) -#define V4L2_CID_PVR_VRES (V4L2_CID_PRIVATE_BASE+12) - -#define V4L2_CID_PVR_MAX (V4L2_CID_PRIVATE_BASE+12) - struct v4l2_capability pvr_capability ={ .driver = "pvrusb2", .card = "Hauppauge WinTV pvr-usb2", @@ -141,69 +125,6 @@ static struct v4l2_tuner pvr_v4l2_tuners[]= { #endif }; -struct v4l2_standard pvr_standards[] = { - [PVR2_CVAL_VIDEOSTANDARD_PAL_BG] = { - .id = V4L2_STD_PAL_BG, - .frameperiod = - { - .numerator = 1, - .denominator= 25 - }, - .framelines = 625, - .reserved = {0,0,0,0} - }, - [PVR2_CVAL_VIDEOSTANDARD_PAL_I] = { - .id = V4L2_STD_PAL_I, - .frameperiod = - { - .numerator = 1, - .denominator= 25 - }, - .framelines = 625, - .reserved = {0,0,0,0} - }, - [PVR2_CVAL_VIDEOSTANDARD_PAL_DK] = { - .id = V4L2_STD_PAL_DK, - .frameperiod = - { - .numerator = 1, - .denominator= 25 - }, - .framelines = 625, - .reserved = {0,0,0,0} - }, - [PVR2_CVAL_VIDEOSTANDARD_SECAM_L] = { - .id = V4L2_STD_SECAM, - .frameperiod = - { - .numerator = 1, - .denominator= 25 - }, - .framelines = 625, - .reserved = {0,0,0,0} - }, - [PVR2_CVAL_VIDEOSTANDARD_NTSC_M] = { - .id = V4L2_STD_NTSC_M, - .frameperiod = - { - .numerator = 1001, - .denominator= 30000 - }, - .framelines = 525, - .reserved = {0,0,0,0} - }, - [PVR2_CVAL_VIDEOSTANDARD_PAL_M] = { - .id = V4L2_STD_PAL_M, - .frameperiod = - { - .numerator = 1001, - .denominator= 30000 - }, - .framelines = 525, - .reserved = {0,0,0,0} - } -}; - struct v4l2_fmtdesc pvr_fmtdesc [] = { { .index = 0, @@ -257,84 +178,6 @@ struct v4l2_format pvr_format [] = { } }; -static int cnv_cid_v4l2_pvr2(int id) -{ - switch (id) { - case V4L2_CID_BRIGHTNESS: - return PVR2_CID_BRIGHTNESS; - case V4L2_CID_SATURATION: - return PVR2_CID_SATURATION; - case V4L2_CID_CONTRAST: - return PVR2_CID_CONTRAST; - case V4L2_CID_HUE: - return PVR2_CID_HUE; - case V4L2_CID_AUDIO_VOLUME: - return PVR2_CID_VOLUME; - case V4L2_CID_AUDIO_BALANCE: - return PVR2_CID_BALANCE; - case V4L2_CID_AUDIO_BASS: - return PVR2_CID_BASS; - case V4L2_CID_AUDIO_TREBLE: - return PVR2_CID_TREBLE; - case V4L2_CID_AUDIO_MUTE: - return PVR2_CID_MUTE; - case V4L2_CID_PVR_SRATE: - return PVR2_CID_SRATE; - case V4L2_CID_PVR_AUDIOBITRATE: - return PVR2_CID_AUDIOBITRATE; - case V4L2_CID_PVR_AUDIOCRC: - return PVR2_CID_AUDIOCRC; - case V4L2_CID_PVR_AUDIOEMPHASIS: - return PVR2_CID_AUDIOEMPHASIS; - case V4L2_CID_PVR_VBR: - return PVR2_CID_VBR; - case V4L2_CID_PVR_VIDEOBITRATE: - return PVR2_CID_AVERAGEVIDEOBITRATE; - case V4L2_CID_PVR_VIDEOPEAK: - return PVR2_CID_PEAKVIDEOBITRATE; - case V4L2_CID_PVR_INPUT: - return PVR2_CID_INPUT; - case V4L2_CID_PVR_AUDIOMODE: - return PVR2_CID_AUDIOMODE; - case V4L2_CID_PVR_FREQUENCY: - return PVR2_CID_FREQUENCY; - case V4L2_CID_PVR_HRES: - return PVR2_CID_HRES; - case V4L2_CID_PVR_VRES: - return PVR2_CID_VRES; - } - return -1; -} - -#if 0 -static int cnv_cid_pvr2_v4l2(int id) -{ - switch (id) { - case PVR2_CID_BRIGHTNESS: - return V4L2_CID_BRIGHTNESS; - case PVR2_CID_SATURATION: - return V4L2_CID_SATURATION; - case PVR2_CID_CONTRAST: - return V4L2_CID_CONTRAST; - case PVR2_CID_HUE: - return V4L2_CID_HUE; - case PVR2_CID_VOLUME: - return V4L2_CID_AUDIO_VOLUME; - case PVR2_CID_BALANCE: - return V4L2_CID_AUDIO_BALANCE; - case PVR2_CID_BASS: - return V4L2_CID_AUDIO_BASS; - case PVR2_CID_TREBLE: - return V4L2_CID_AUDIO_TREBLE; - case PVR2_CID_MUTE: - return V4L2_CID_AUDIO_MUTE; - - return id + V4L2_CID_PRIVATE_BASE; - } - return -1; -} -#endif - /* * pvr_ioctl() * @@ -402,22 +245,15 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_ENUMSTD: { - struct v4l2_standard *vs = (struct v4l2_standard *)arg; + const struct v4l2_standard *src; int idx = vs->index; - if ((vs->index < PVR2_CVAL_VIDEOSTANDARD_MIN) || - (vs->index > PVR2_CVAL_VIDEOSTANDARD_MAX)) { - break; - } + src = pvr2_hdw_get_stdenum_value(hdw,idx); + if (!src) break; - memcpy(vs, &pvr_standards[idx], sizeof(struct v4l2_standard)); + memcpy(vs, src, sizeof(struct v4l2_standard)); vs->index = idx; - strlcpy(vs->name, - pvr2_hdw_get_ctl_value_name(hdw, - PVR2_CID_VIDEOSTANDARD, - idx), - sizeof(vs->name)); ret = 0; break; @@ -425,59 +261,37 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_STD: { + struct pvr2_ctrl *cptr; v4l2_std_id *vs = (v4l2_std_id *)arg; - - switch (pvr2_hdw_get_ctl_value(hdw,PVR2_CID_VIDEOSTANDARD)) { - default: - case PVR2_CVAL_VIDEOSTANDARD_NTSC_M: - *vs = V4L2_STD_NTSC_M; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_M: - *vs = V4L2_STD_PAL_M; - break; - case PVR2_CVAL_VIDEOSTANDARD_SECAM_L: - *vs = V4L2_STD_SECAM; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_BG: - *vs = V4L2_STD_PAL_BG; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_I: - *vs = V4L2_STD_PAL_I; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_DK: - *vs = V4L2_STD_PAL_DK; + cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_STDCUR); + if (!pvr2_ctrl_is_valid(cptr)) { + ret = -EINVAL; break; } + + *vs = pvr2_ctrl_get_value(cptr); ret = 0; break; } case VIDIOC_S_STD: { + struct pvr2_ctrl *cptr; v4l2_std_id *vs = (v4l2_std_id *)arg; - int val = PVR2_CVAL_VIDEOSTANDARD_NTSC_M; - - if (*vs & V4L2_STD_NTSC_M){ - val = PVR2_CVAL_VIDEOSTANDARD_NTSC_M; - } else if (*vs & V4L2_STD_PAL_BG){ - val = PVR2_CVAL_VIDEOSTANDARD_PAL_BG; - } else if (*vs & V4L2_STD_PAL_I){ - val = PVR2_CVAL_VIDEOSTANDARD_PAL_I; - } else if (*vs & V4L2_STD_PAL_DK){ - val = PVR2_CVAL_VIDEOSTANDARD_PAL_DK; - } else if (*vs & V4L2_STD_SECAM){ - val = PVR2_CVAL_VIDEOSTANDARD_SECAM_L; - } else if (*vs & V4L2_STD_PAL_M){ - val = PVR2_CVAL_VIDEOSTANDARD_PAL_M; + cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_STDCUR); + if (!pvr2_ctrl_is_valid(cptr)) { + ret = -EINVAL; + break; } - pvr2_hdw_set_ctl_value(hdw,PVR2_CID_VIDEOSTANDARD,val); - + pvr2_ctrl_set_value(cptr,*vs); + ret = 0; break; } case VIDIOC_ENUMINPUT: { + struct pvr2_ctrl *cptr; struct v4l2_input *vi = (struct v4l2_input *)arg; struct v4l2_input tmp; @@ -486,6 +300,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, break; } + cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_INPUT); + memset(&tmp,0,sizeof(tmp)); tmp.index = vi->index; switch (vi->index) { @@ -500,8 +316,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, } strlcpy(tmp.name, - pvr2_hdw_get_ctl_value_name(hdw,PVR2_CID_INPUT, - vi->index), + pvr2_ctrl_get_value_name(cptr,vi->index), sizeof(tmp.name)); /* Don't bother with audioset, since this driver currently @@ -522,17 +337,31 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_INPUT: { + struct pvr2_ctrl *cptr; struct v4l2_input *vi = (struct v4l2_input *)arg; - vi->index = pvr2_hdw_get_ctl_value(hdw,PVR2_CID_INPUT); + cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_INPUT); + if (!pvr2_ctrl_is_valid(cptr)) { + ret = -EINVAL; + break; + } + + vi->index = pvr2_ctrl_get_value(cptr); ret = 0; break; } case VIDIOC_S_INPUT: { + struct pvr2_ctrl *cptr; struct v4l2_input *vi = (struct v4l2_input *)arg; + cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_INPUT); + if (!pvr2_ctrl_is_valid(cptr)) { + ret = -EINVAL; + break; + } + ret = 0; - if (pvr2_hdw_set_ctl_value(hdw,PVR2_CID_INPUT,vi->index)) { + if (pvr2_ctrl_set_value(cptr,vi->index)) { ret = -EINVAL; } break; @@ -557,6 +386,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, } case VIDIOC_G_TUNER: { + struct pvr2_ctrl *cptr; struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; unsigned int status_mask; if (vt->index !=0) break; @@ -580,26 +410,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, vt->signal = 65535; } - switch (pvr2_hdw_get_ctl_value(hdw,PVR2_CID_AUDIOMODE)) { - case PVR2_CVAL_AUDIOMODE_MONO: - vt->audmode = V4L2_TUNER_MODE_MONO; - break; - case PVR2_CVAL_AUDIOMODE_STEREO: - vt->audmode = V4L2_TUNER_MODE_STEREO; - break; - case PVR2_CVAL_AUDIOMODE_LANG1: - vt->audmode = V4L2_TUNER_MODE_LANG1; - break; - case PVR2_CVAL_AUDIOMODE_LANG2: - vt->audmode = V4L2_TUNER_MODE_LANG2; - break; - case PVR2_CVAL_AUDIOMODE_LANG1_LANG2: - vt->audmode = V4L2_TUNER_MODE_LANG1_LANG2; - break; - case PVR2_CVAL_AUDIOMODE_SAP: - vt->audmode = V4L2_TUNER_MODE_SAP; - break; - } + cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_AUDIOMODE); + vt->audmode = pvr2_ctrl_get_value(cptr); ret = 0; break; @@ -607,40 +419,34 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_S_TUNER: { + struct pvr2_ctrl *cptr; struct v4l2_tuner *vt=(struct v4l2_tuner *)arg; - int val = PVR2_CVAL_AUDIOMODE_STEREO; if (vt->index != 0) break; - switch (vt->audmode) { - case V4L2_TUNER_MODE_MONO: - val = PVR2_CVAL_AUDIOMODE_MONO; - break; - case V4L2_TUNER_MODE_STEREO: - val = PVR2_CVAL_AUDIOMODE_STEREO; - break; - case V4L2_TUNER_MODE_LANG1: - val = PVR2_CVAL_AUDIOMODE_LANG1; - break; - case V4L2_TUNER_MODE_LANG1_LANG2: - val = PVR2_CVAL_AUDIOMODE_LANG1_LANG2; - break; - case V4L2_TUNER_MODE_SAP: // Also LANG2 - val = PVR2_CVAL_AUDIOMODE_SAP; + cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_AUDIOMODE); + if (!pvr2_ctrl_is_valid(cptr)) { + ret = -EINVAL; break; } - pvr2_hdw_set_ctl_value(hdw,PVR2_CID_AUDIOMODE,val); + pvr2_ctrl_set_value(cptr,vt->audmode); ret = 0; } case VIDIOC_S_FREQUENCY: { + struct pvr2_ctrl *cptr; const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; - pvr2_hdw_set_ctl_value(hdw,PVR2_CID_FREQUENCY, - vf->frequency * 62500); + cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_FREQUENCY); + if (!pvr2_ctrl_is_valid(cptr)) { + ret = -EINVAL; + break; + } + + pvr2_ctrl_set_value(cptr,vf->frequency * 62500); ret = 0; break; @@ -648,10 +454,17 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_FREQUENCY: { + struct pvr2_ctrl *cptr; struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; int val; - val = pvr2_hdw_get_ctl_value(hdw,PVR2_CID_FREQUENCY); + cptr = pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_FREQUENCY); + if (!pvr2_ctrl_is_valid(cptr)) { + ret = -EINVAL; + break; + } + + val = pvr2_ctrl_get_value(cptr); val /= 62500; vf->frequency = val; @@ -682,12 +495,18 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format)); vf->fmt.pix.width = - pvr2_hdw_get_ctl_value(hdw,PVR2_CID_HRES); - if (pvr2_hdw_get_ctl_value(hdw,PVR2_CID_INTERLACE)) { + pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl(hdw, + V4L2_CID_PVR_HRES)); + if (pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl( + hdw,V4L2_CID_PVR_INTERLACE))) { vf->fmt.pix.width /= 2; } vf->fmt.pix.height = - pvr2_hdw_get_ctl_value(hdw,PVR2_CID_VRES); + pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl(hdw, + V4L2_CID_PVR_VRES)); ret = 0; break; case V4L2_BUF_TYPE_VBI_CAPTURE: @@ -713,16 +532,12 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, int w = vf->fmt.pix.width; int vd_std, hf, hh; - vd_std = pvr2_hdw_get_ctl_value(hdw, - PVR2_CID_VIDEOSTANDARD); - switch (vd_std) { - case PVR2_CVAL_VIDEOSTANDARD_NTSC_M: - case PVR2_CVAL_VIDEOSTANDARD_PAL_M: + vd_std = pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl(hdw,V4L2_CID_PVR_STDCUR)); + if (vd_std & V4L2_STD_525_60) { hf=480; - break; - default: + } else { hf=576; - break; } hh = (int) (hf / 2); @@ -734,15 +549,18 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, vf->fmt.pix.height = (h > hh) ? hf : hh; if (cmd == VIDIOC_S_FMT){ - pvr2_hdw_set_ctl_value( - hdw,PVR2_CID_HRES, + pvr2_ctrl_set_value( + pvr2_hdw_get_ctrl(hdw, + V4L2_CID_PVR_HRES), vf->fmt.pix.width); - pvr2_hdw_set_ctl_value( - hdw,PVR2_CID_VRES, + pvr2_ctrl_set_value( + pvr2_hdw_get_ctrl(hdw, + V4L2_CID_PVR_VRES), vf->fmt.pix.height); - pvr2_hdw_set_ctl_value( - hdw,PVR2_CID_INTERLACE, - (vf->fmt.pix.height != hf)); + pvr2_ctrl_set_value( + pvr2_hdw_get_ctrl( + hdw,V4L2_CID_PVR_INTERLACE), + vf->fmt.pix.height != hf); } } break; case V4L2_BUF_TYPE_VBI_CAPTURE: @@ -772,22 +590,31 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_QUERYCTRL: { + struct pvr2_ctrl *cptr; struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg; - int pvr2_id = cnv_cid_v4l2_pvr2(vc->id); - if (pvr2_id < 0) { + cptr = pvr2_hdw_get_ctrl(hdw,vc->id); + + if (!pvr2_ctrl_is_valid(cptr)) { ret = -EINVAL; break; } - if (pvr2_hdw_get_ctl_value_name(hdw,pvr2_id,0)) { + switch (pvr2_ctrl_get_type(cptr)) { + case PVR2_CTRL_TYPE_ENUM: vc->type = V4L2_CTRL_TYPE_MENU; - } else { + break; + case PVR2_CTRL_TYPE_INT: vc->type = V4L2_CTRL_TYPE_INTEGER; + break; + default: + ret = -EINVAL; + break; } - strlcpy(vc->name,pvr2_hdw_get_ctl_name(hdw,pvr2_id), - sizeof(vc->name)); - vc->minimum = pvr2_hdw_get_ctl_min_value(hdw,pvr2_id); - vc->maximum = pvr2_hdw_get_ctl_max_value(hdw,pvr2_id); + + strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name)); + vc->minimum = pvr2_ctrl_get_min_value(cptr); + vc->maximum = pvr2_ctrl_get_max_value(cptr); + vc->default_value = pvr2_ctrl_get_default_value(cptr); vc->step = 1; ret = 0; break; @@ -795,16 +622,15 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_QUERYMENU: { + struct pvr2_ctrl *cptr; struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg; - int pvr2_id = cnv_cid_v4l2_pvr2(vm->id); const char *value_name; - if (pvr2_id < 0) { + cptr = pvr2_hdw_get_ctrl(hdw,vm->id); + if (!pvr2_ctrl_is_valid(cptr)) { ret = -EINVAL; break; } - - value_name = pvr2_hdw_get_ctl_value_name(hdw,pvr2_id, - vm->index); + value_name = pvr2_ctrl_get_value_name(cptr,vm->index); if (value_name) { strlcpy(vm->name,value_name,sizeof(vm->name)); ret = 0; @@ -817,31 +643,31 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_CTRL: { + struct pvr2_ctrl *cptr; struct v4l2_control *vc = (struct v4l2_control *)arg; - int pvr2_id; - pvr2_id = cnv_cid_v4l2_pvr2(vc->id); - if (pvr2_id < 0) { + cptr = pvr2_hdw_get_ctrl(hdw,vc->id); + if (!pvr2_ctrl_is_valid(cptr)) { ret = -EINVAL; break; } ret = 0; - vc->value = pvr2_hdw_get_ctl_value(hdw,pvr2_id); + vc->value = pvr2_ctrl_get_value(cptr); break; } case VIDIOC_S_CTRL: { + struct pvr2_ctrl *cptr; struct v4l2_control *vc = (struct v4l2_control *)arg; - int pvr2_id; - pvr2_id = cnv_cid_v4l2_pvr2(vc->id); - if (pvr2_id < 0) { + cptr = pvr2_hdw_get_ctrl(hdw,vc->id); + if (!pvr2_ctrl_is_valid(cptr)) { ret = -EINVAL; break; } - ret = pvr2_hdw_set_ctl_value(hdw,pvr2_id,vc->value); + ret = pvr2_ctrl_set_value(cptr,vc->value); break; } |