From f44c0bc49cbb5ee3bd7d89c602873840d40c8b25 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 26 Mar 2006 15:45:31 -0600 Subject: Get rid of static PVR2_CID_COUNT in pvrusb2 From: Mike Isely Eliminate the need to track the number pvrusb2 CIDs at compile time from within the pvrusb2 driver. This is part of a control structure cleanup. Signed-off-by: Mike Isely --- .../media/video/pvrusb2/pvrusb2-hdw-internal.h | 2 +- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 80 ++++++++++++++++++---- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h | 6 +- linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 2 +- 4 files changed, 73 insertions(+), 17 deletions(-) (limited to 'linux/drivers/media') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 05e44385b..25854375b 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -211,7 +211,7 @@ 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_ctl_state *controls; }; int pvr2_hdw_set_ctl_value_internal(struct pvr2_hdw *hdw, diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index ec2b5eeae..81a35a8e2 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -97,6 +97,7 @@ struct pvr2_ctl_def { int min_value; int skip_init; int default_value; + int is_valid; const char **value_defs_ptr; unsigned int value_defs_count; }; @@ -184,63 +185,73 @@ 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 struct pvr2_ctl_def control_defs[] = { [PVR2_CID_BRIGHTNESS] = { + .is_valid = !0, .name = "Brightness", .min_value = 0, .max_value = 255, .default_value = 128, }, [PVR2_CID_CONTRAST] = { + .is_valid = !0, .name = "Contrast", .min_value = 0, .max_value = 127, .default_value = 68, }, [PVR2_CID_SATURATION] = { + .is_valid = !0, .name = "Saturation", .min_value = 0, .max_value = 127, .default_value = 64, }, [PVR2_CID_HUE] = { + .is_valid = !0, .name = "Hue", .min_value = -128, .max_value = 127, .default_value = 0, }, [PVR2_CID_VOLUME] = { + .is_valid = !0, .name = "Volume", .min_value = 0, .max_value = 65535, .default_value = 65535, }, [PVR2_CID_BALANCE] = { + .is_valid = !0, .name = "Balance", .min_value = -32768, .max_value = 32767, .default_value = 0, }, [PVR2_CID_BASS] = { + .is_valid = !0, .name = "Bass", .min_value = -32768, .max_value = 32767, .default_value = 0, }, [PVR2_CID_TREBLE] = { + .is_valid = !0, .name = "Treble", .min_value = -32768, .max_value = 32767, .default_value = 0, }, [PVR2_CID_MUTE] = { + .is_valid = !0, .name = "Mute", .min_value = 0, .max_value = 1, .default_value = 0, }, [PVR2_CID_SRATE] = { + .is_valid = !0, .name = "Sample rate", .min_value = PVR2_CVAL_SRATE_MIN, .max_value = PVR2_CVAL_SRATE_MAX, @@ -248,6 +259,7 @@ static struct pvr2_ctl_def control_defs[PVR2_CID_COUNT] = VDEF(control_values_srate), }, [PVR2_CID_AUDIOBITRATE] = { + .is_valid = !0, .name = "Audio Bitrate", .min_value = PVR2_CVAL_AUDIOBITRATE_MIN, .max_value = PVR2_CVAL_AUDIOBITRATE_MAX, @@ -255,12 +267,14 @@ static struct pvr2_ctl_def control_defs[PVR2_CID_COUNT] = VDEF(control_values_audiobitrate), }, [PVR2_CID_AUDIOCRC] = { + .is_valid = !0, .name = "Audio CRC", .min_value = 0, .max_value = 1, .default_value = 1, }, [PVR2_CID_AUDIOEMPHASIS] = { + .is_valid = !0, .name = "Audio Emphasis", .min_value = PVR2_CVAL_AUDIOEMPHASIS_MIN, .max_value = PVR2_CVAL_AUDIOEMPHASIS_MAX, @@ -268,24 +282,28 @@ static struct pvr2_ctl_def control_defs[PVR2_CID_COUNT] = VDEF(control_values_audioemphasis), }, [PVR2_CID_VBR] = { + .is_valid = !0, .name = "Variable video bitrate", .min_value = 0, .max_value = 1, .default_value = 0, }, [PVR2_CID_AVERAGEVIDEOBITRATE] = { + .is_valid = !0, .name = "Average video bitrate", .min_value = 1, .max_value = 20000000, .default_value = 6000000, }, [PVR2_CID_PEAKVIDEOBITRATE] = { + .is_valid = !0, .name = "Peak video bitrate", .min_value = 1, .max_value = 20000000, .default_value = 6000000, }, [PVR2_CID_VIDEOSTANDARD] = { + .is_valid = !0, .name = "Video Standard", .min_value = PVR2_CVAL_VIDEOSTANDARD_MIN, .max_value = PVR2_CVAL_VIDEOSTANDARD_MAX, @@ -293,6 +311,7 @@ static struct pvr2_ctl_def control_defs[PVR2_CID_COUNT] = VDEF(control_values_videostandard), }, [PVR2_CID_INPUT] = { + .is_valid = !0, .name = "Video Source", .min_value = PVR2_CVAL_INPUT_MIN, .max_value = PVR2_CVAL_INPUT_MAX, @@ -300,6 +319,7 @@ static struct pvr2_ctl_def control_defs[PVR2_CID_COUNT] = VDEF(control_values_input), }, [PVR2_CID_AUDIOMODE] = { + .is_valid = !0, .name = "Audio Mode", .min_value = PVR2_CVAL_AUDIOMODE_MIN, .max_value = PVR2_CVAL_AUDIOMODE_MAX, @@ -307,48 +327,56 @@ static struct pvr2_ctl_def control_defs[PVR2_CID_COUNT] = VDEF(control_values_audiomode), }, [PVR2_CID_FREQUENCY] = { + .is_valid = !0, .name = "Tuner Frequency (Hz)", .min_value = 55250000L, .max_value = 850000000L, .default_value = 175250000L, }, [PVR2_CID_HRES] = { + .is_valid = !0, .name = "Horizontal capture resolution", .min_value = 320, .max_value = 720, .default_value = 720, }, [PVR2_CID_VRES] = { + .is_valid = !0, .name = "Vertical capture resolution", .min_value = 200, .max_value = 625, .default_value = 480, }, [PVR2_CID_INTERLACE] = { + .is_valid = !0, .name = "Interlace mode", .min_value = 0, .max_value = 1, .default_value = 0, }, [PVR2_CID_AUDIOLAYER] = { + .is_valid = !0, .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] = { + .is_valid = !0, .name = "Channel", .min_value = 0, .max_value = FREQTABLE_SIZE, .default_value = 0, }, [PVR2_CID_CHANPROG_ID] = { + .is_valid = !0, .name = "Channel Program ID", .min_value = 0, .max_value = FREQTABLE_SIZE, .default_value = 0, }, [PVR2_CID_CHANPROG_FREQ] = { + .is_valid = !0, .name = "Channel Program Frequency", .min_value = 55250000L, .max_value = 850000000L, @@ -357,18 +385,21 @@ static struct pvr2_ctl_def control_defs[PVR2_CID_COUNT] = .get_func = pvr2_ctl_get_chanprog_id, }, [PVR2_CID_SIGNAL_PRESENT] = { + .is_valid = !0, .name = "Signal Present", .min_value = 0, .max_value = 1, .get_func = pvr2_ctl_get_signal, }, [PVR2_CID_STREAMING_ENABLED] = { + .is_valid = !0, .name = "Streaming Enabled", .min_value = 0, .max_value = 1, .get_func = pvr2_ctl_get_streaming, }, [PVR2_CID_HSM] = { + .is_valid = !0, .name = "USB Speed", .min_value = PVR2_CVAL_HSM_MIN, .max_value = PVR2_CVAL_HSM_MAX, @@ -376,6 +407,7 @@ static struct pvr2_ctl_def control_defs[PVR2_CID_COUNT] = VDEF(control_values_hsm), }, [PVR2_CID_SUBSYS_MASK] = { + .is_valid = !0, .name = "Subsystem enabled mask", .min_value = 0, .max_value = 0x7fffffff, @@ -384,6 +416,7 @@ static struct pvr2_ctl_def control_defs[PVR2_CID_COUNT] = .set_func = pvr2_ctl_set_subsys_mask, }, [PVR2_CID_SUBSYS_STREAM_MASK] = { + .is_valid = !0, .name = "Subsystem stream mask", .min_value = 0, .max_value = 0x7fffffff, @@ -395,6 +428,7 @@ static struct pvr2_ctl_def control_defs[PVR2_CID_COUNT] = #undef VDEF +#define CTRL_COUNT (sizeof(control_defs)/sizeof(control_defs[0])) const char *pvr2_config_get_name(enum pvr2_config cfg) { @@ -1106,7 +1140,7 @@ 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++) { + for (idx = 0; idx < CTRL_COUNT; idx++) { if (control_defs[idx].skip_init) continue; pvr2_hdw_set_ctl_value_internal( hdw,idx,control_defs[idx].default_value); @@ -1259,6 +1293,9 @@ 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)); + hdw->controls = kmalloc(sizeof(struct pvr2_ctl_state) * CTRL_COUNT, + GFP_KERNEL); + if (!hdw->controls) goto fail; hdw->hdw_type = hdw_type; hdw->eeprom_addr = -1; @@ -1322,6 +1359,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 +1424,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) unit_pointers[hdw->unit_number] = 0; } } while (0); up(&pvr2_unit_sem); + kfree(hdw->controls); kfree(hdw); } @@ -1447,7 +1486,9 @@ int pvr2_hdw_get_ctl_value(struct pvr2_hdw *hdw,unsigned int ctl_id) { int ret = 0; - if (ctl_id >= PVR2_CID_COUNT) return 0; + if (ctl_id >= CTRL_COUNT) return 0; + if (!control_defs[ctl_id].is_valid) 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); @@ -1462,7 +1503,8 @@ int pvr2_hdw_get_ctl_value(struct pvr2_hdw *hdw,unsigned int ctl_id) /* Return true if control is writable */ int pvr2_hdw_get_ctl_rw(struct pvr2_hdw *hdw,unsigned int ctl_id) { - if (ctl_id >= PVR2_CID_COUNT) return 0; + if (ctl_id >= CTRL_COUNT) return 0; + if (!control_defs[ctl_id].is_valid) return 0; if (control_defs[ctl_id].get_func && !control_defs[ctl_id].set_func) { return 0; } @@ -1473,7 +1515,8 @@ int pvr2_hdw_get_ctl_rw(struct pvr2_hdw *hdw,unsigned int ctl_id) /* Retrieve legal minimum value for a given control */ int pvr2_hdw_get_ctl_min_value(struct pvr2_hdw *hdw,unsigned int ctl_id) { - if (ctl_id >= PVR2_CID_COUNT) return 0; + if (ctl_id >= CTRL_COUNT) return 0; + if (!control_defs[ctl_id].is_valid) return 0; return control_defs[ctl_id].min_value; } @@ -1481,7 +1524,8 @@ int pvr2_hdw_get_ctl_min_value(struct pvr2_hdw *hdw,unsigned int ctl_id) /* Retrieve legal maximum value for a given control */ int pvr2_hdw_get_ctl_max_value(struct pvr2_hdw *hdw,unsigned int ctl_id) { - if (ctl_id >= PVR2_CID_COUNT) return 0; + if (ctl_id >= CTRL_COUNT) return 0; + if (!control_defs[ctl_id].is_valid) return 0; return control_defs[ctl_id].max_value; } @@ -1492,7 +1536,8 @@ int pvr2_hdw_set_ctl_value_internal(struct pvr2_hdw *hdw, unsigned int ctl_id,int value) { int ret; - if (ctl_id >= PVR2_CID_COUNT) return -EINVAL; + if (ctl_id >= CTRL_COUNT) return -EINVAL; + if (!control_defs[ctl_id].is_valid) 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) { @@ -1532,7 +1577,8 @@ const char *pvr2_hdw_get_ctl_value_name(struct pvr2_hdw *hdw, int value) { struct pvr2_ctl_def *cdef; - if (ctl_id >= PVR2_CID_COUNT) return 0; + if (ctl_id >= CTRL_COUNT) return 0; + if (!control_defs[ctl_id].is_valid) return 0; cdef = control_defs + ctl_id; if (! cdef->value_defs_ptr) return 0; if (value >= cdef->value_defs_count) return 0; @@ -1543,11 +1589,21 @@ const char *pvr2_hdw_get_ctl_value_name(struct pvr2_hdw *hdw, /* Retrieve string name for given control */ const char *pvr2_hdw_get_ctl_name(struct pvr2_hdw *hdw,unsigned int ctl_id) { - if (ctl_id >= PVR2_CID_COUNT) return 0; + if (ctl_id >= CTRL_COUNT) return 0; + if (!control_defs[ctl_id].is_valid) return 0; return control_defs[ctl_id].name; } +/* Return true if control ID is a valid id */ +int pvr2_hdw_get_ctl_valid(struct pvr2_hdw *hdw,unsigned int ctl_id) +{ + if (ctl_id >= CTRL_COUNT) return 0; + if (!control_defs[ctl_id].is_valid) return 0; + return !0; +} + + /* Commit all control changes made up to this point. Subsystems can be indirectly affected by these changes. For a given set of things being committed, we'll clear the affected subsystem bits and then once we're @@ -1595,7 +1651,7 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) } } - for (idx = 0; idx < PVR2_CID_COUNT; idx++) { + for (idx = 0; idx < CTRL_COUNT; idx++) { if (!hdw->controls[idx].dirty) continue; if (!commit_flag) { commit_flag = !0; @@ -1671,7 +1727,7 @@ 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++) { + for (idx = 0; idx < CTRL_COUNT; idx++) { hdw->controls[idx].dirty = 0; } @@ -1733,7 +1789,7 @@ void pvr2_hdw_poll_trigger(struct pvr2_hdw *hdw) through this value. */ unsigned int pvr2_hdw_get_ctl_count(struct pvr2_hdw *hdw) { - return PVR2_CID_COUNT; + return CTRL_COUNT; } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h index aa6d9029a..6cc841b56 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -59,9 +59,6 @@ #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 @@ -234,6 +231,9 @@ int pvr2_hdw_set_ctl_value(struct pvr2_hdw *,unsigned int ctl_id,int value); /* Retrieve string name for given control */ const char *pvr2_hdw_get_ctl_name(struct pvr2_hdw *,unsigned int ctl_id); +/* Return true if control id is a valid id */ +int pvr2_hdw_get_ctl_valid(struct pvr2_hdw *,unsigned int ctl_id); + /* 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 *, diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index f82fd643c..6b81def26 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -30,7 +30,7 @@ #define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__) -static char *item_names[PVR2_CID_COUNT] = { +static char *item_names[] = { [PVR2_CID_BRIGHTNESS] = "ctl_brightness", [PVR2_CID_CONTRAST] = "ctl_contrast", [PVR2_CID_SATURATION] = "ctl_saturation", -- cgit v1.2.3 From da1de2e42e2a5c0290c15edbbd4017176ff0b1c2 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 26 Mar 2006 15:46:35 -0600 Subject: Propagate default control values out to V4L apps from within pvrusb2 From: Mike Isely When a V4L app queries a pvrusb2 control, make sure we also tell it what the control's default value is. Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 9 +++++++++ linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h | 3 +++ linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 2 ++ 3 files changed, 14 insertions(+) (limited to 'linux/drivers/media') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 81a35a8e2..a0b0cd8aa 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1530,6 +1530,15 @@ int pvr2_hdw_get_ctl_max_value(struct pvr2_hdw *hdw,unsigned int ctl_id) } +/* Retrieve default value for a given control */ +int pvr2_hdw_get_ctl_default_value(struct pvr2_hdw *hdw,unsigned int ctl_id) +{ + if (ctl_id >= CTRL_COUNT) return 0; + if (!control_defs[ctl_id].is_valid) return 0; + return control_defs[ctl_id].default_value; +} + + /* 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, diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 6cc841b56..d7749138c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -224,6 +224,9 @@ int pvr2_hdw_get_ctl_min_value(struct pvr2_hdw *,unsigned int ctl_id); /* Retrieve legal maximum value for a given control */ int pvr2_hdw_get_ctl_max_value(struct pvr2_hdw *,unsigned int ctl_id); +/* Retrieve legal maximum value for a given control */ +int pvr2_hdw_get_ctl_default_value(struct pvr2_hdw *,unsigned int ctl_id); + /* 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); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index dd207fae4..4cdd08708 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -788,6 +788,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, 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); + vc->default_value = + pvr2_hdw_get_ctl_default_value(hdw,pvr2_id); vc->step = 1; ret = 0; break; -- cgit v1.2.3 From d213c7fd61512ba8605208f6b785829ff1da017b Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 28 Mar 2006 22:05:31 -0600 Subject: Major pvrusb2 rework to remove translations From: Mike Isely Rework entire internal controls interface to eliminate the need for visibly defined control IDs which must otherwise be translated by the V4L2 public interface. As part of this work, internal structures which mimiced various V4L2 structures (video standards, audio modes) have been reworked to actually use the native structures. This triggered a _significant_ rework for how video standards are dealt with (and what is in place now should be much more flexible and forgiving for various handling less-common video standards). Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-audio.c | 23 +- linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c | 44 +- linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.h | 1 - .../drivers/media/video/pvrusb2/pvrusb2-encoder.c | 12 +- .../media/video/pvrusb2/pvrusb2-hdw-internal.h | 123 ++- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 956 ++++++++++++++++----- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h | 199 ++--- .../media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 30 +- linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 120 ++- linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 402 +++------ 10 files changed, 1134 insertions(+), 776 deletions(-) (limited to 'linux/drivers/media') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c index 79395d540..ae34ff9e4 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..634095efc 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c @@ -204,7 +204,7 @@ 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); @@ -222,48 +222,6 @@ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw) -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 553bd2d7b..2de5b6c8f 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 25854375b..189075bbe 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; }; @@ -191,7 +294,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 +320,17 @@ struct pvr2_hdw { struct pvr2_audio_stat *audio_stat; /* Every last bit of controllable state */ - struct pvr2_ctl_state *controls; + 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 a0b0cd8aa..585f4ee0b 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "pvrusb2.h" #include "pvrusb2-util.h" @@ -86,23 +87,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; - int is_valid; - 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", @@ -136,12 +120,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", }; @@ -154,12 +161,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", }; @@ -174,210 +180,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 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] = { + .id = V4L2_CID_BRIGHTNESS, .is_valid = !0, - .name = "Brightness", + .desc = "Brightness", + .name = "brightness", .min_value = 0, .max_value = 255, .default_value = 128, }, [PVR2_CID_CONTRAST] = { + .id = V4L2_CID_CONTRAST, .is_valid = !0, - .name = "Contrast", + .desc = "Contrast", + .name = "contrast", .min_value = 0, .max_value = 127, .default_value = 68, }, [PVR2_CID_SATURATION] = { + .id = V4L2_CID_SATURATION, .is_valid = !0, - .name = "Saturation", + .desc = "Saturation", + .name = "saturation", .min_value = 0, .max_value = 127, .default_value = 64, }, [PVR2_CID_HUE] = { + .id = V4L2_CID_HUE, .is_valid = !0, - .name = "Hue", + .desc = "Hue", + .name = "hue", .min_value = -128, .max_value = 127, .default_value = 0, }, [PVR2_CID_VOLUME] = { + .id = V4L2_CID_AUDIO_VOLUME, .is_valid = !0, - .name = "Volume", + .desc = "Volume", + .name = "volume", .min_value = 0, .max_value = 65535, .default_value = 65535, }, [PVR2_CID_BALANCE] = { + .id = V4L2_CID_AUDIO_BALANCE, .is_valid = !0, - .name = "Balance", + .desc = "Balance", + .name = "balance", .min_value = -32768, .max_value = 32767, .default_value = 0, }, [PVR2_CID_BASS] = { + .id = V4L2_CID_AUDIO_BASS, .is_valid = !0, - .name = "Bass", + .desc = "Bass", + .name = "bass", .min_value = -32768, .max_value = 32767, .default_value = 0, }, [PVR2_CID_TREBLE] = { + .id = V4L2_CID_AUDIO_TREBLE, .is_valid = !0, - .name = "Treble", + .desc = "Treble", + .name = "treble", .min_value = -32768, .max_value = 32767, .default_value = 0, }, [PVR2_CID_MUTE] = { + .id = V4L2_CID_AUDIO_MUTE, .is_valid = !0, - .name = "Mute", + .desc = "Mute", + .name = "mute", .min_value = 0, .max_value = 1, .default_value = 0, }, [PVR2_CID_SRATE] = { + .id = V4L2_CID_PVR_SRATE, .is_valid = !0, - .name = "Sample rate", + .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] = { + .id = V4L2_CID_PVR_AUDIOBITRATE, .is_valid = !0, - .name = "Audio Bitrate", + .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] = { + .id = V4L2_CID_PVR_AUDIOCRC, .is_valid = !0, - .name = "Audio CRC", + .desc = "Audio CRC", + .name = "audio_crc", .min_value = 0, .max_value = 1, .default_value = 1, }, [PVR2_CID_AUDIOEMPHASIS] = { + .id = V4L2_CID_PVR_AUDIOEMPHASIS, .is_valid = !0, - .name = "Audio Emphasis", + .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] = { + .id = V4L2_CID_PVR_VBR, .is_valid = !0, - .name = "Variable video bitrate", + .desc = "Variable video bitrate", + .name = "vbr", .min_value = 0, .max_value = 1, .default_value = 0, }, [PVR2_CID_AVERAGEVIDEOBITRATE] = { + .id = V4L2_CID_PVR_VIDEOBITRATE, .is_valid = !0, - .name = "Average video bitrate", + .desc = "Average video bitrate", + .name = "video_average_bitrate", .min_value = 1, .max_value = 20000000, .default_value = 6000000, }, [PVR2_CID_PEAKVIDEOBITRATE] = { + .id = V4L2_CID_PVR_VIDEOPEAK, .is_valid = !0, - .name = "Peak video bitrate", + .desc = "Peak video bitrate", + .name = "video_peak_bitrate", .min_value = 1, .max_value = 20000000, .default_value = 6000000, }, - [PVR2_CID_VIDEOSTANDARD] = { + [PVR2_CID_STDAVAIL] = { .is_valid = !0, - .name = "Video Standard", - .min_value = PVR2_CVAL_VIDEOSTANDARD_MIN, - .max_value = PVR2_CVAL_VIDEOSTANDARD_MAX, - .default_value = PVR2_CVAL_VIDEOSTANDARD_NTSC_M, + .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] = { + .id = V4L2_CID_PVR_INPUT, .is_valid = !0, - .name = "Video Source", + .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] = { + .id = V4L2_CID_PVR_AUDIOMODE, .is_valid = !0, - .name = "Audio Mode", - .min_value = PVR2_CVAL_AUDIOMODE_MIN, - .max_value = PVR2_CVAL_AUDIOMODE_MAX, - .default_value = PVR2_CVAL_AUDIOMODE_STEREO, + .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] = { + .id = V4L2_CID_PVR_FREQUENCY, .is_valid = !0, - .name = "Tuner Frequency (Hz)", + .desc = "Tuner Frequency (Hz)", + .name = "frequency", .min_value = 55250000L, .max_value = 850000000L, .default_value = 175250000L, }, [PVR2_CID_HRES] = { + .id = V4L2_CID_PVR_HRES, .is_valid = !0, - .name = "Horizontal capture resolution", + .desc = "Horizontal capture resolution", + .name = "resolution_hor", .min_value = 320, .max_value = 720, .default_value = 720, }, [PVR2_CID_VRES] = { + .id = V4L2_CID_PVR_VRES, .is_valid = !0, - .name = "Vertical capture resolution", + .desc = "Vertical capture resolution", + .name = "resolution_ver", .min_value = 200, .max_value = 625, .default_value = 480, }, [PVR2_CID_INTERLACE] = { + .id = V4L2_CID_PVR_INTERLACE, .is_valid = !0, - .name = "Interlace mode", + .desc = "Interlace mode", + .name = "interlace", .min_value = 0, .max_value = 1, .default_value = 0, }, [PVR2_CID_AUDIOLAYER] = { .is_valid = !0, - .name = "Audio Layer", + .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] = { .is_valid = !0, - .name = "Channel", + .desc = "Channel", + .name = "channel", .min_value = 0, .max_value = FREQTABLE_SIZE, .default_value = 0, }, [PVR2_CID_CHANPROG_ID] = { .is_valid = !0, - .name = "Channel Program ID", + .desc = "Channel Program ID", + .name = "freq_table_channel", .min_value = 0, .max_value = FREQTABLE_SIZE, .default_value = 0, }, [PVR2_CID_CHANPROG_FREQ] = { .is_valid = !0, - .name = "Channel Program Frequency", + .desc = "Channel Program Frequency", + .name = "freq_table_value", .min_value = 55250000L, .max_value = 850000000L, .skip_init = !0, @@ -386,21 +447,24 @@ static struct pvr2_ctl_def control_defs[] = }, [PVR2_CID_SIGNAL_PRESENT] = { .is_valid = !0, - .name = "Signal Present", + .desc = "Signal Present", + .name = "signal_present", .min_value = 0, .max_value = 1, .get_func = pvr2_ctl_get_signal, }, [PVR2_CID_STREAMING_ENABLED] = { .is_valid = !0, - .name = "Streaming Enabled", + .desc = "Streaming Enabled", + .name = "streaming_enabled", .min_value = 0, .max_value = 1, .get_func = pvr2_ctl_get_streaming, }, [PVR2_CID_HSM] = { .is_valid = !0, - .name = "USB Speed", + .desc = "USB Speed", + .name = "usb_speed", .min_value = PVR2_CVAL_HSM_MIN, .max_value = PVR2_CVAL_HSM_MAX, .get_func = pvr2_ctl_get_hsm, @@ -408,7 +472,8 @@ static struct pvr2_ctl_def control_defs[] = }, [PVR2_CID_SUBSYS_MASK] = { .is_valid = !0, - .name = "Subsystem enabled mask", + .desc = "Subsystem enabled mask", + .name = "debug_subsys_mask", .min_value = 0, .max_value = 0x7fffffff, .skip_init = !0, @@ -417,18 +482,33 @@ static struct pvr2_ctl_def control_defs[] = }, [PVR2_CID_SUBSYS_STREAM_MASK] = { .is_valid = !0, - .name = "Subsystem stream mask", + .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_COUNT (sizeof(control_defs)/sizeof(control_defs[0])) +#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) { @@ -978,9 +1058,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; } @@ -1095,6 +1175,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 @@ -1141,9 +1222,11 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) if (!pvr2_hdw_dev_ok(hdw)) return; for (idx = 0; idx < CTRL_COUNT; idx++) { - if (control_defs[idx].skip_init) continue; - pvr2_hdw_set_ctl_value_internal( - hdw,idx,control_defs[idx].default_value); + 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); @@ -1172,7 +1255,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); @@ -1293,11 +1390,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)); - hdw->controls = kmalloc(sizeof(struct pvr2_ctl_state) * CTRL_COUNT, + + // 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; @@ -1425,6 +1546,8 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) } } 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); } @@ -1453,10 +1576,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; @@ -1470,149 +1594,584 @@ 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; + } + + 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; +} - if (ctl_id >= CTRL_COUNT) return 0; - if (!control_defs[ctl_id].is_valid) 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; +// 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 >= CTRL_COUNT) return 0; - if (!control_defs[ctl_id].is_valid) 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 >= CTRL_COUNT) return 0; - if (!control_defs[ctl_id].is_valid) 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; } -/* Retrieve legal maximum value for a given control */ -int pvr2_hdw_get_ctl_max_value(struct pvr2_hdw *hdw,unsigned int ctl_id) +static int pvr2_ctl_get_stdenumcur(struct pvr2_ctrl *cptr) { - if (ctl_id >= CTRL_COUNT) return 0; - if (!control_defs[ctl_id].is_valid) return 0; - return control_defs[ctl_id].max_value; + return cptr->hdw->std_id; } -/* Retrieve default value for a given control */ -int pvr2_hdw_get_ctl_default_value(struct pvr2_hdw *hdw,unsigned int ctl_id) +static int pvr2_ctl_get_stdavail(struct pvr2_ctrl *cptr) { - if (ctl_id >= CTRL_COUNT) return 0; - if (!control_defs[ctl_id].is_valid) return 0; - return control_defs[ctl_id].default_value; + return (int)(cptr->hdw->video_std_avail); } -/* 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) +/* 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; +} + + +/* 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) +{ + 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 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 >= CTRL_COUNT) return -EINVAL; - if (!control_defs[ctl_id].is_valid) 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 >= CTRL_COUNT) return 0; - if (!control_defs[ctl_id].is_valid) 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 >= CTRL_COUNT) return 0; - if (!control_defs[ctl_id].is_valid) 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 true if control ID is a valid id */ -int pvr2_hdw_get_ctl_valid(struct pvr2_hdw *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 *cptr) { - if (ctl_id >= CTRL_COUNT) return 0; - if (!control_defs[ctl_id].is_valid) return 0; + 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; +} + + /* Commit all control changes made up to this point. Subsystems can be indirectly affected by these changes. For a given set of things being committed, we'll clear the affected subsystem bits and then once we're @@ -1625,6 +2184,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; @@ -1661,16 +2222,17 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) } for (idx = 0; idx < CTRL_COUNT; idx++) { - if (!hdw->controls[idx].dirty) continue; + 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 = ""; } @@ -1690,16 +2252,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) { @@ -1712,7 +2271,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 || @@ -1737,7 +2296,8 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) pvr2_i2c_core_check_stale(hdw); for (idx = 0; idx < CTRL_COUNT; idx++) { - hdw->controls[idx].dirty = 0; + cptr = hdw->controls + idx; + cptr->dirty = 0; } /* Now execute i2c core update */ @@ -1794,14 +2354,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 CTRL_COUNT; -} - - /* Return name for this driver instance */ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw) { @@ -1837,36 +2389,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; @@ -1888,10 +2440,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 d7749138c..4101f4097 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -21,86 +21,37 @@ #ifndef __PVRUSB2_HDW_H #define __PVRUSB2_HDW_H +#include "compat.h" #include +#include #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 - -/* 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 @@ -110,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 @@ -164,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, @@ -212,43 +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 true if control is writable */ -int pvr2_hdw_get_ctl_rw(struct pvr2_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 *); -/* Retrieve legal minimum value for a given control */ -int pvr2_hdw_get_ctl_min_value(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 maximum value for a given control */ -int pvr2_hdw_get_ctl_max_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_default_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 *); -/* Return true if control id is a valid id */ -int pvr2_hdw_get_ctl_valid(struct pvr2_hdw *,unsigned int ctl_id); +/* 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 *); -/* 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 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-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 +#include 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-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 6b81def26..0ded41fcb 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -30,41 +30,6 @@ #define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__) -static char *item_names[] = { - [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; @@ -88,11 +53,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[25]; }; struct pvr2_sysfs_class { @@ -101,13 +67,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 +86,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 +102,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 +119,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 +137,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 +158,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 +166,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 +181,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 +201,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 +233,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 +271,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 +382,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 +443,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 +452,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 +503,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,7 +522,10 @@ 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); @@ -573,12 +569,10 @@ static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp) 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); } } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 4cdd08708..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,24 +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); - vc->default_value = - pvr2_hdw_get_ctl_default_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; @@ -797,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; @@ -819,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; } -- cgit v1.2.3 From 0d7fd3cdc85eb7e7e64a735ee7242aad047f4d64 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 28 Mar 2006 23:36:32 -0600 Subject: Fix pvrusb2 kernel oops From: Mike Isely This problem was introduced by the previous change. It appears that if you try to create to sysfs entries of the same name in one directory, then sysfs gets very angry and causes a kernel oops when you later try to tear down those nodes. By not allocating enough space to hold the name, we were inadvertently causing a sysfs control file name collision... Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers/media') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 0ded41fcb..c5d44aa6c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -58,7 +58,7 @@ struct pvr2_sysfs_ctl_item { struct pvr2_sysfs_ctl_item *item_next; struct attribute *attr_gen[5]; struct attribute_group grp; - char name[25]; + char name[80]; }; struct pvr2_sysfs_class { -- cgit v1.2.3 From 896235d467ecdcaecf352dae6d1970fdda4caeec Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 29 Mar 2006 02:00:23 -0600 Subject: Enhance I2C debugging in pvrusb2 From: Mike Isely Enhance I2C debugging in pvrusb2 such that I2C data is printed when transactions are reported. Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'linux/drivers/media') 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); } -- cgit v1.2.3 From df9faeeb73f7e2d40d144d32b07dbc8560b5e031 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 29 Mar 2006 02:01:58 -0600 Subject: Don't reset USB control state during pvrusb2 initialization From: Mike Isely Initialization failures in the pvrusb2 driver seem to coincide with attempts to reset parts of the USB core related to this device. This really should not be needed and I suspect it may be doing more harm than good. Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers/media') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 585f4ee0b..7b27d96ab 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1229,8 +1229,10 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) cptr->ctl_def->default_value); } +#if 0 // Suspect this is doing more harm than good pvr2_reset_ctl_endpoints(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; +#endif ret = pvr2_hdw_get_eeprom_addr(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; -- cgit v1.2.3 From 376fb9365c967e7d2bb2aee61e01685595bf1111 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Thu, 30 Mar 2006 22:14:40 -0600 Subject: Make parts of pvrusb2 compile-time options (sysfs and debugifc) From: Mike Isely Arrange things in pvrusb2 so that the sysfs-using component doesn't have to be compiled in. Control this with new CONFIG_VIDEO_PVRUSB2_SYSFS variable. This will allow the driver to still be used even if sysfs has not been compiled into the kernel. Also arrange things similarly in pvrusb2 for the debug interface, which is something that normally should not need to be built but is valuable for bug chasing. This is controlled now with CONFIG_VIDEO_PVRUSB2_DEBUGIFC. Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-main.c | 10 ++++++++++ linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 14 ++++++++++++++ 2 files changed, 24 insertions(+) (limited to 'linux/drivers/media') 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 " #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 c5d44aa6c..053c0b24c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -26,14 +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__) 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; @@ -42,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; @@ -531,6 +537,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) 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); @@ -565,6 +572,7 @@ 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) @@ -608,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); @@ -684,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 */ } @@ -755,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; @@ -787,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 */ /* -- cgit v1.2.3 From 012c447c3dd586921468215450cb6cce65052a3c Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Thu, 30 Mar 2006 22:16:09 -0600 Subject: pvrusb2 driver initialization tweak From: Mike Isely Make permanent the removal of the call to pvr2_reset_ctl_endpoints(). It is known positively now that this step was both unneeded and caused harm to communication with the hardware during driver initialization. Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'linux/drivers/media') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 7b27d96ab..32bdaeba7 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1229,10 +1229,9 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) cptr->ctl_def->default_value); } -#if 0 // Suspect this is doing more harm than good - pvr2_reset_ctl_endpoints(hdw); - if (!pvr2_hdw_dev_ok(hdw)) return; -#endif + // 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; -- cgit v1.2.3 From 401def2d2cdb15034aa721cc524c9d7c70d3ddcd Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Thu, 30 Mar 2006 22:51:33 -0600 Subject: Clean up comments in pvrusb2-eeprom.c From: Mike Isely Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c | 72 +--------------------- 1 file changed, 2 insertions(+), 70 deletions(-) (limited to 'linux/drivers/media') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c index 634095efc..78bc968c0 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-eeprom.c @@ -27,57 +27,8 @@ #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 */ - /* Read and analyze data in the eeprom. Use tveeprom to figure out @@ -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; @@ -211,17 +154,6 @@ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw) return 0; } - - -/* END DIRECT METHOD, V4L ONLY */ -/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - - - - - - - /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** -- cgit v1.2.3 From 0bce98602d455b54f9e8f4915f7288e0b4b6bdb8 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 31 Mar 2006 01:47:58 -0500 Subject: Kconfig: add menu options for pvrusb2 sysfs and debug interface support From: Michael Krufky Signed-off-by: Michael Krufky --- linux/drivers/media/video/pvrusb2/Kconfig | 27 +++++++++++++++++++++++++++ linux/drivers/media/video/pvrusb2/Makefile | 7 +++++-- 2 files changed, 32 insertions(+), 2 deletions(-) (limited to 'linux/drivers/media') diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 9824ad267..b22ab7f5f 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -12,3 +12,30 @@ config VIDEO_PVRUSB2 To compile this driver as a module, choose M here: the module will be called pvrusb2 + +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..b0d3064ef 100644 --- a/linux/drivers/media/video/pvrusb2/Makefile +++ b/linux/drivers/media/video/pvrusb2/Makefile @@ -1,11 +1,14 @@ +obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o +obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.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-context.o pvrusb2-io.o pvrusb2-ioread.o \ pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \ - pvrusb2-ioread.o pvrusb2-debugifc.o + $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y) obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o -- cgit v1.2.3 From 29fafe9bd09810fa43e5db62eebc23b985f68180 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 1 Apr 2006 16:00:41 -0500 Subject: Kconfig: fix VP-3054 Secondary I2C Bus build configuration menu dependencies From: Michael Krufky This patch fixes a dependency problem that affected the indentation order within the individual frontend selection support menus for cx88-dvb. - created a boolean dependency link for VIDEO_CX88_VP3054, so that it's tristate value will be the same as that of VIDEO_CX88_DVB. - VIDEO_CX88_VP3054 is automatically selected by VIDEO_CX88_DVB_ALL_FRONTENDS, but is otherwise selected by VIDEO_CX88_DVB_VP3054, offered as an option under VIDEO_CX88_DVB_MT352 Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx88/Kconfig | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'linux/drivers/media') 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, -- cgit v1.2.3 From cbea0cdfe46b67fb696b0a045e8ace7dddf4ca49 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 1 Apr 2006 20:36:50 -0600 Subject: Split out PVR USB2 model 24xxx hardware support to a config option From: Mike Isely Since there are lingering stability problems with support of the newer PVR USB2 model 24xxx series hardware, I have isolate those changes with a config option. This commit leaves that option off. Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/Kconfig | 18 ++++++++++++++++++ linux/drivers/media/video/pvrusb2/Makefile | 6 +++++- .../drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 2 ++ linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 8 ++++++++ .../media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | 4 ++++ 5 files changed, 37 insertions(+), 1 deletion(-) (limited to 'linux/drivers/media') diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index b22ab7f5f..629dc4e05 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -13,6 +13,24 @@ 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 diff --git a/linux/drivers/media/video/pvrusb2/Makefile b/linux/drivers/media/video/pvrusb2/Makefile index b0d3064ef..53fccce4f 100644 --- a/linux/drivers/media/video/pvrusb2/Makefile +++ b/linux/drivers/media/video/pvrusb2/Makefile @@ -1,13 +1,17 @@ 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-context.o pvrusb2-io.o pvrusb2-ioread.o \ - pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.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-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 189075bbe..9c5f0f74c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -199,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 diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 32bdaeba7..f0de1e154 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -38,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 { } }; @@ -46,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}; @@ -625,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; @@ -636,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 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; -- cgit v1.2.3