summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c')
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c956
1 files changed, 754 insertions, 202 deletions
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 <linux/string.h>
#include <linux/slab.h>
#include <linux/firmware.h>
+#include <linux/videodev2.h>
#include <asm/semaphore.h>
#include "pvrusb2.h"
#include "pvrusb2-util.h"
@@ -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 = "<out of range>";
}
@@ -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);
}