diff options
Diffstat (limited to 'linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c')
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1485 |
1 files changed, 579 insertions, 906 deletions
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f0de1e154..9ea68eeef 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -24,9 +24,9 @@ #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-std.h" #include "pvrusb2-util.h" #include "pvrusb2-hdw.h" #include "pvrusb2-i2c-core.h" @@ -123,39 +123,6 @@ static const char *control_values_audioemphasis[] = { }; -static const char *control_values_videostandard[] = { - "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", -}; - - static const char *control_values_input[] = { [PVR2_CVAL_INPUT_TV] = "television", /*xawtv needs this name*/ [PVR2_CVAL_INPUT_RADIO] = "radio", @@ -180,339 +147,515 @@ static const char *control_values_hsm[] = { }; -#define VDEF(x) \ - .value_defs_ptr = x, \ - .value_defs_count = (sizeof(x)/sizeof(x[0])) - -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, +// ????? Need to tie these to bit positions +static const char *control_values_subsystem[] = { + "enc_firmware", + "enc_config", + "digitizer_run", + "usbstream_run", + "enc_run", +}; + + +static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp) +{ + struct pvr2_hdw *hdw = cptr->hdw; + if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) { + *vp = hdw->freqTable[hdw->freqProgSlot-1]; + } else { + *vp = 0; + } + return 0; +} + +static int ctrl_channelfreq_set(struct pvr2_ctrl *cptr,int m,int v) +{ + struct pvr2_hdw *hdw = cptr->hdw; + if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) { + hdw->freqTable[hdw->freqProgSlot-1] = v; + } + return 0; +} + +static int ctrl_channelprog_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->freqProgSlot; + return 0; +} + +static int ctrl_channelprog_set(struct pvr2_ctrl *cptr,int m,int v) +{ + struct pvr2_hdw *hdw = cptr->hdw; + if ((v >= 0) && (v <= FREQTABLE_SIZE)) { + hdw->freqProgSlot = v; + } + return 0; +} + +static int ctrl_channel_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->freqSlot; + return 0; +} + +static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int v) +{ + unsigned freq = 0; + struct pvr2_hdw *hdw = cptr->hdw; + hdw->freqSlot = v; + if ((hdw->freqSlot > 0) && (hdw->freqSlot <= FREQTABLE_SIZE)) { + freq = hdw->freqTable[hdw->freqSlot-1]; + } + if (freq && (freq != hdw->freqVal)) { + hdw->freqVal = freq; + hdw->freqDirty = !0; + } + return 0; +} + +static int ctrl_freq_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->freqVal; + return 0; +} + +static int ctrl_freq_is_dirty(struct pvr2_ctrl *cptr) +{ + return cptr->hdw->freqDirty != 0; +} + +static void ctrl_freq_clear_dirty(struct pvr2_ctrl *cptr) +{ + cptr->hdw->freqDirty = 0; +} + +static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) +{ + struct pvr2_hdw *hdw = cptr->hdw; + hdw->freqVal = v; + hdw->freqDirty = !0; + hdw->freqSlot = 0; + return 0; +} + +static int ctrl_streamingenabled_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->flag_streaming_enabled; + return 0; +} + +static int ctrl_hsm_get(struct pvr2_ctrl *cptr,int *vp) +{ + int result = pvr2_hdw_is_hsm(cptr->hdw); + *vp = PVR2_CVAL_HSM_FULL; + if (result < 0) *vp = PVR2_CVAL_HSM_FAIL; + if (result) *vp = PVR2_CVAL_HSM_HIGH; + return 0; +} + +static int ctrl_stdavail_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->video_std_avail; + return 0; +} + +static int ctrl_std_val_to_sym(struct pvr2_ctrl *cptr,int msk,int val, + char *bufPtr,unsigned int bufSize, + unsigned int *len) +{ + *len = pvr2_std_id_to_str(bufPtr,bufSize,msk & val); + return 0; +} + +static int ctrl_std_sym_to_val(struct pvr2_ctrl *cptr, + const char *bufPtr,unsigned int bufSize, + int *mskp,int *valp) +{ + int ret; + v4l2_std_id id; + ret = pvr2_std_str_to_id(&id,bufPtr,bufSize); + if (ret < 0) return ret; + if (mskp) *mskp = id; + if (valp) *valp = id; + return 0; +} + +static int ctrl_stdcur_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->video_std_cur; + return 0; +} + +static int ctrl_stdcur_set(struct pvr2_ctrl *cptr,int m,int v) +{ + pvr2_hdw_internal_set_std_cur(cptr->hdw,v); + return 0; +} + +static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = ((pvr2_hdw_get_signal_status_internal(cptr->hdw) & + PVR2_SIGNAL_OK) ? 1 : 0); + return 0; +} + +static int ctrl_subsys_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->subsys_enabled_mask; + return 0; +} + +static int ctrl_subsys_set(struct pvr2_ctrl *cptr,int m,int v) +{ + pvr2_hdw_subsys_bit_chg_no_lock(cptr->hdw,m,v); + return 0; +} + +static int ctrl_subsys_stream_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->subsys_stream_mask; + return 0; +} + +static int ctrl_subsys_stream_set(struct pvr2_ctrl *cptr,int m,int v) +{ + pvr2_hdw_subsys_stream_bit_chg_no_lock(cptr->hdw,m,v); + return 0; +} + +static int ctrl_stdenumcur_set(struct pvr2_ctrl *cptr,int m,int v) +{ + if (v < 0) return -EINVAL; + if (v >= cptr->hdw->std_cnt) return -EINVAL; + cptr->hdw->std_id = v; + pvr2_hdw_internal_set_std_cur(cptr->hdw, + cptr->hdw->std_id); + return 0; +} + + +static int ctrl_stdenumcur_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->std_id; + return 0; +} + + +static int ctrl_stdenumcur_is_dirty(struct pvr2_ctrl *cptr) +{ + return cptr->hdw->video_std_dirty != 0; +} + + +static void ctrl_stdenumcur_clear_dirty(struct pvr2_ctrl *cptr) +{ + cptr->hdw->video_std_dirty = 0; +} + + +#define DEFINT(vmin,vmax) \ + .type = pvr2_ctl_int, \ + .def.type_int.min_value = vmin, \ + .def.type_int.max_value = vmax + +#define DEFENUM(tab) \ + .type = pvr2_ctl_enum, \ + .def.type_enum.count = (sizeof(tab)/sizeof((tab)[0])), \ + .def.type_enum.value_names = tab + +#define DEFMASK(msk,tab) \ + .type = pvr2_ctl_bitmask, \ + .def.type_bitmask.valid_bits = msk, \ + .def.type_bitmask.bit_names = tab + +#define DEFREF(vname) \ + .set_value = ctrl_set_##vname, \ + .get_value = ctrl_get_##vname, \ + .is_dirty = ctrl_isdirty_##vname, \ + .clear_dirty = ctrl_cleardirty_##vname + + +#define VCREATE_FUNCS(vname) \ +static int ctrl_get_##vname(struct pvr2_ctrl *cptr,int *vp) \ +{*vp = cptr->hdw->vname##_val; return 0;} \ +static int ctrl_set_##vname(struct pvr2_ctrl *cptr,int m,int v) \ +{cptr->hdw->vname##_val = v; cptr->hdw->vname##_dirty = !0; return 0;} \ +static int ctrl_isdirty_##vname(struct pvr2_ctrl *cptr) \ +{return cptr->hdw->vname##_dirty != 0;} \ +static void ctrl_cleardirty_##vname(struct pvr2_ctrl *cptr) \ +{cptr->hdw->vname##_dirty = 0;} + +VCREATE_FUNCS(brightness) +VCREATE_FUNCS(contrast) +VCREATE_FUNCS(saturation) +VCREATE_FUNCS(hue) +VCREATE_FUNCS(volume) +VCREATE_FUNCS(balance) +VCREATE_FUNCS(bass) +VCREATE_FUNCS(treble) +VCREATE_FUNCS(mute) +VCREATE_FUNCS(srate) +VCREATE_FUNCS(audiobitrate) +VCREATE_FUNCS(audiocrc) +VCREATE_FUNCS(audioemphasis) +VCREATE_FUNCS(vbr) +VCREATE_FUNCS(videobitrate) +VCREATE_FUNCS(videopeak) +VCREATE_FUNCS(input) +VCREATE_FUNCS(audiomode) +VCREATE_FUNCS(res_hor) +VCREATE_FUNCS(res_ver) +VCREATE_FUNCS(interlace) +VCREATE_FUNCS(audiolayer) + +#define MIN_FREQ 55250000L +#define MAX_FREQ 850000000L + +/* Table definition of all controls which can be manipulated */ +static const struct pvr2_ctl_info control_defs[] = { + { + .v4l_id = V4L2_CID_BRIGHTNESS, .desc = "Brightness", .name = "brightness", - .min_value = 0, - .max_value = 255, .default_value = 128, - }, - [PVR2_CID_CONTRAST] = { - .id = V4L2_CID_CONTRAST, - .is_valid = !0, + DEFREF(brightness), + DEFINT(0,255), + },{ + .v4l_id = V4L2_CID_CONTRAST, .desc = "Contrast", .name = "contrast", - .min_value = 0, - .max_value = 127, .default_value = 68, - }, - [PVR2_CID_SATURATION] = { - .id = V4L2_CID_SATURATION, - .is_valid = !0, + DEFREF(contrast), + DEFINT(0,127), + },{ + .v4l_id = V4L2_CID_SATURATION, .desc = "Saturation", .name = "saturation", - .min_value = 0, - .max_value = 127, .default_value = 64, - }, - [PVR2_CID_HUE] = { - .id = V4L2_CID_HUE, - .is_valid = !0, + DEFREF(saturation), + DEFINT(0,127), + },{ + .v4l_id = V4L2_CID_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, + DEFREF(hue), + DEFINT(-128,127), + },{ + .v4l_id = V4L2_CID_AUDIO_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, + DEFREF(volume), + DEFINT(0,65535), + },{ + .v4l_id = V4L2_CID_AUDIO_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, + DEFREF(balance), + DEFINT(-32768,32767), + },{ + .v4l_id = V4L2_CID_AUDIO_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, + DEFREF(bass), + DEFINT(-32768,32767), + },{ + .v4l_id = V4L2_CID_AUDIO_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, + DEFREF(treble), + DEFINT(-32768,32767), + },{ + .v4l_id = V4L2_CID_AUDIO_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, + DEFREF(mute), + DEFINT(0,1), + },{ + .v4l_id = V4L2_CID_PVR_SRATE, .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, + DEFREF(srate), + DEFENUM(control_values_srate), + },{ + .v4l_id = V4L2_CID_PVR_AUDIOBITRATE, .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, + DEFREF(audiobitrate), + DEFENUM(control_values_audiobitrate), + },{ + .v4l_id = V4L2_CID_PVR_AUDIOCRC, .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, + DEFREF(audiocrc), + DEFINT(0,1), + },{ + .desc = "Audio Layer", + .name = "audio_layer", + .default_value = 2, + DEFREF(audiolayer), + DEFINT(0,3), + },{ + .v4l_id = V4L2_CID_PVR_AUDIOEMPHASIS, .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, + DEFREF(audioemphasis), + DEFENUM(control_values_audioemphasis), + },{ + .desc = "Interlace mode", + .name = "interlace", + .internal_id = PVR2_CID_INTERLACE, + .default_value = 0, + DEFREF(interlace), + DEFINT(0,1), + },{ + .v4l_id = V4L2_CID_PVR_VBR, .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, + DEFREF(vbr), + DEFINT(0,1), + },{ + .v4l_id = V4L2_CID_PVR_VIDEOBITRATE, .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, + DEFREF(videobitrate), + DEFINT(500000,20000000), + },{ + .v4l_id = V4L2_CID_PVR_VIDEOPEAK, .desc = "Peak video bitrate", .name = "video_peak_bitrate", - .min_value = 1, - .max_value = 20000000, .default_value = 6000000, - }, - [PVR2_CID_STDAVAIL] = { - .is_valid = !0, - .desc = "Video Standards Available Mask", - .name = "video_standard_mask_available", - .min_value = 0, - .max_value = 0, - .default_value = (int)V4L2_STD_UNKNOWN, - .mask_value = (int)V4L2_STD_ALL, - .get_func = pvr2_ctl_get_stdavail, - VDEF(control_values_videostandard), - }, - [PVR2_CID_INPUT] = { - .id = V4L2_CID_PVR_INPUT, - .is_valid = !0, + DEFREF(videopeak), + DEFINT(500000,20000000), + },{ .desc = "Video Source", .name = "input", - .min_value = PVR2_CVAL_INPUT_MIN, - .max_value = PVR2_CVAL_INPUT_MAX, + .internal_id = PVR2_CID_INPUT, .default_value = PVR2_CVAL_INPUT_TV, - VDEF(control_values_input), - }, - [PVR2_CID_AUDIOMODE] = { - .id = V4L2_CID_PVR_AUDIOMODE, - .is_valid = !0, + DEFREF(input), + DEFENUM(control_values_input), + },{ .desc = "Audio Mode", .name = "audio_mode", - .min_value = V4L2_TUNER_MODE_MONO, - .max_value = V4L2_TUNER_MODE_LANG1_LANG2, + .internal_id = PVR2_CID_AUDIOMODE, .default_value = V4L2_TUNER_MODE_STEREO, - VDEF(control_values_audiomode), - }, - [PVR2_CID_FREQUENCY] = { - .id = V4L2_CID_PVR_FREQUENCY, - .is_valid = !0, + DEFREF(audiomode), + DEFENUM(control_values_audiomode), + },{ .desc = "Tuner Frequency (Hz)", .name = "frequency", - .min_value = 55250000L, - .max_value = 850000000L, + .internal_id = PVR2_CID_FREQUENCY, .default_value = 175250000L, - }, - [PVR2_CID_HRES] = { - .id = V4L2_CID_PVR_HRES, - .is_valid = !0, + .set_value = ctrl_freq_set, + .get_value = ctrl_freq_get, + .is_dirty = ctrl_freq_is_dirty, + .clear_dirty = ctrl_freq_clear_dirty, + DEFINT(MIN_FREQ,MAX_FREQ), + },{ + .desc = "Channel", + .name = "channel", + .set_value = ctrl_channel_set, + .get_value = ctrl_channel_get, + DEFINT(0,FREQTABLE_SIZE), + },{ + .desc = "Channel Program Frequency", + .name = "freq_table_value", + .set_value = ctrl_channelfreq_set, + .get_value = ctrl_channelfreq_get, + DEFINT(MIN_FREQ,MAX_FREQ), + },{ + .desc = "Channel Program ID", + .name = "freq_table_channel", + .set_value = ctrl_channelprog_set, + .get_value = ctrl_channelprog_get, + DEFINT(0,FREQTABLE_SIZE), + },{ .desc = "Horizontal capture resolution", .name = "resolution_hor", - .min_value = 320, - .max_value = 720, + .internal_id = PVR2_CID_HRES, .default_value = 720, - }, - [PVR2_CID_VRES] = { - .id = V4L2_CID_PVR_VRES, - .is_valid = !0, + DEFREF(res_hor), + DEFINT(320,720), + },{ .desc = "Vertical capture resolution", .name = "resolution_ver", - .min_value = 200, - .max_value = 625, + .internal_id = PVR2_CID_VRES, .default_value = 480, - }, - [PVR2_CID_INTERLACE] = { - .id = V4L2_CID_PVR_INTERLACE, - .is_valid = !0, - .desc = "Interlace mode", - .name = "interlace", - .min_value = 0, - .max_value = 1, - .default_value = 0, - }, - [PVR2_CID_AUDIOLAYER] = { - .is_valid = !0, - .desc = "Audio Layer", - .name = "audio_layer", - .min_value = 0, /* This is all a wild guess */ - .max_value = 3, - .default_value = 2, /* Appears to be all that is supported */ - }, - [PVR2_CID_CHANNEL] = { - .is_valid = !0, - .desc = "Channel", - .name = "channel", - .min_value = 0, - .max_value = FREQTABLE_SIZE, - .default_value = 0, - }, - [PVR2_CID_CHANPROG_ID] = { - .is_valid = !0, - .desc = "Channel Program ID", - .name = "freq_table_channel", - .min_value = 0, - .max_value = FREQTABLE_SIZE, - .default_value = 0, - }, - [PVR2_CID_CHANPROG_FREQ] = { - .is_valid = !0, - .desc = "Channel Program Frequency", - .name = "freq_table_value", - .min_value = 55250000L, - .max_value = 850000000L, - .skip_init = !0, - .set_func = pvr2_ctl_set_chanprog_id, - .get_func = pvr2_ctl_get_chanprog_id, - }, - [PVR2_CID_SIGNAL_PRESENT] = { - .is_valid = !0, - .desc = "Signal Present", - .name = "signal_present", - .min_value = 0, - .max_value = 1, - .get_func = pvr2_ctl_get_signal, - }, - [PVR2_CID_STREAMING_ENABLED] = { - .is_valid = !0, + DEFREF(res_ver), + DEFINT(200,625), + },{ .desc = "Streaming Enabled", .name = "streaming_enabled", - .min_value = 0, - .max_value = 1, - .get_func = pvr2_ctl_get_streaming, - }, - [PVR2_CID_HSM] = { - .is_valid = !0, + .get_value = ctrl_streamingenabled_get, + DEFINT(0,1), + },{ .desc = "USB Speed", .name = "usb_speed", - .min_value = PVR2_CVAL_HSM_MIN, - .max_value = PVR2_CVAL_HSM_MAX, - .get_func = pvr2_ctl_get_hsm, - VDEF(control_values_hsm), - }, - [PVR2_CID_SUBSYS_MASK] = { - .is_valid = !0, + .get_value = ctrl_hsm_get, + DEFENUM(control_values_hsm), + },{ + .desc = "Signal Present", + .name = "signal_present", + .get_value = ctrl_signal_get, + DEFINT(0,1), + },{ + .desc = "Video Standards Available Mask", + .name = "video_standard_mask_available", + .internal_id = PVR2_CID_STDAVAIL, + .get_value = ctrl_stdavail_get, + .val_to_sym = ctrl_std_val_to_sym, + .sym_to_val = ctrl_std_sym_to_val, + .type = pvr2_ctl_bitmask, + },{ + .desc = "Video Standards In Use Mask", + .name = "video_standard_mask_active", + .internal_id = PVR2_CID_STDCUR, + .skip_init = !0, + .get_value = ctrl_stdcur_get, + .set_value = ctrl_stdcur_set, + .val_to_sym = ctrl_std_val_to_sym, + .sym_to_val = ctrl_std_sym_to_val, + .type = pvr2_ctl_bitmask, + },{ .desc = "Subsystem enabled mask", .name = "debug_subsys_mask", - .min_value = 0, - .max_value = 0x7fffffff, .skip_init = !0, - .get_func = pvr2_ctl_get_subsys_mask, - .set_func = pvr2_ctl_set_subsys_mask, - }, - [PVR2_CID_SUBSYS_STREAM_MASK] = { - .is_valid = !0, + .get_value = ctrl_subsys_get, + .set_value = ctrl_subsys_set, + DEFMASK(PVR2_SUBSYS_ALL,control_values_subsystem), + },{ .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), - }, + .get_value = ctrl_subsys_stream_get, + .set_value = ctrl_subsys_stream_set, + DEFMASK(PVR2_SUBSYS_ALL,control_values_subsystem), + },{ + .desc = "Video Standard Name", + .name = "video_standard", + .internal_id = PVR2_CID_STDENUM, + .skip_init = !0, + .get_value = ctrl_stdenumcur_get, + .set_value = ctrl_stdenumcur_set, + .is_dirty = ctrl_stdenumcur_is_dirty, + .clear_dirty = ctrl_stdenumcur_clear_dirty, + .type = pvr2_ctl_enum, + } }; -#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) { @@ -1066,12 +1209,6 @@ void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw, } -static int pvr2_ctl_get_streaming(struct pvr2_ctrl *cptr) -{ - return cptr->hdw->flag_streaming_enabled != 0; -} - - int pvr2_hdw_set_streaming_no_lock(struct pvr2_hdw *hdw,int enableFl) { if ((!enableFl) == !(hdw->flag_streaming_enabled)) return 0; @@ -1231,10 +1368,9 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) for (idx = 0; idx < CTRL_COUNT; idx++) { cptr = hdw->controls + idx; - if (!pvr2_ctrl_is_valid(cptr)) continue; - if (cptr->ctl_def->skip_init) continue; - pvr2_ctrl_internal_set_value(cptr, - cptr->ctl_def->default_value); + if (cptr->info->skip_init) continue; + if (!cptr->info->set_value) continue; + cptr->info->set_value(cptr,~0,cptr->info->default_value); } // Do not use pvr2_reset_ctl_endpoints() here. It is not @@ -1384,6 +1520,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, unsigned int idx,cnt1,cnt2; struct pvr2_hdw *hdw; unsigned int hdw_type; + int valid_std_mask; + struct pvr2_ctrl *cptr; __u8 ifnum; hdw_type = devid - pvr2_device_table; @@ -1400,33 +1538,61 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, if (!hdw) goto fail; memset(hdw,0,sizeof(*hdw)); - // Initialize video standard enum dynamic control - hdw->video_std_enum.name = "video_standard"; - hdw->video_std_enum.desc = "Video Standard Name"; - hdw->video_std_enum.id = 0; // ????? - hdw->video_std_enum.set_func = pvr2_ctl_set_stdenumcur; - hdw->video_std_enum.get_func = pvr2_ctl_get_stdenumcur; - hdw->video_std_enum.mask_value = 0; - hdw->video_std_enum.max_value = 0; - hdw->video_std_enum.min_value = 0; - hdw->video_std_enum.default_value = 0; - hdw->video_std_enum.is_valid = !0; - hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * CTRL_COUNT, GFP_KERNEL); if (!hdw->controls) goto fail; memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * CTRL_COUNT); hdw->hdw_type = hdw_type; - for (idx = 0; idx < CTRL_DEF_COUNT; idx++) { - hdw->controls[idx].hdw = hdw; - hdw->controls[idx].ctl_def = control_defs + idx; - hdw->controls[idx].is_valid = - hdw->controls[idx].ctl_def->is_valid; + for (idx = 0; idx < 32; idx++) { + hdw->video_std_mask_ptrs[idx] = + hdw->video_std_mask_names[idx]; + } + + for (idx = 0; idx < CTRL_COUNT; idx++) { + cptr = hdw->controls + idx; + cptr->hdw = hdw; + cptr->info = control_defs+idx; + } + + // Initialize video standard enum dynamic control + cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDENUM); + if (cptr) { + memcpy(&hdw->video_std_info_enum,cptr->info, + sizeof(hdw->video_std_info_enum)); + cptr->info = &hdw->video_std_info_enum; + + } + // Initialize control data regarding video standard masks + valid_std_mask = pvr2_std_get_usable(); + for (idx = 0; idx < 32; idx++) { + if (!(valid_std_mask & (1 << idx))) continue; + cnt1 = pvr2_std_id_to_str( + hdw->video_std_mask_names[idx], + sizeof(hdw->video_std_mask_names[idx])-1, + 1 << idx); + hdw->video_std_mask_names[idx][cnt1] = 0; + } + cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDAVAIL); + if (cptr) { + memcpy(&hdw->video_std_info_avail,cptr->info, + sizeof(hdw->video_std_info_avail)); + cptr->info = &hdw->video_std_info_avail; + hdw->video_std_info_avail.def.type_bitmask.bit_names = + hdw->video_std_mask_ptrs; + hdw->video_std_info_avail.def.type_bitmask.valid_bits = + valid_std_mask; + } + cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR); + if (cptr) { + memcpy(&hdw->video_std_info_cur,cptr->info, + sizeof(hdw->video_std_info_cur)); + cptr->info = &hdw->video_std_info_cur; + hdw->video_std_info_cur.def.type_bitmask.bit_names = + hdw->video_std_mask_ptrs; + hdw->video_std_info_avail.def.type_bitmask.valid_bits = + valid_std_mask; } - 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; @@ -1556,7 +1722,7 @@ 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); + if (hdw->video_std_enum_names) kfree(hdw->video_std_enum_names); kfree(hdw); } @@ -1585,221 +1751,26 @@ void pvr2_hdw_disconnect(struct pvr2_hdw *hdw) } -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; - if (hdw->controls[PVR2_CID_CHANNEL].value == id) { - /* If the current channel happens to be the slot we just - set, then act like the current channel just got changed - so we'll update that too. */ - hdw->controls[PVR2_CID_CHANNEL].dirty = !0; - } - return 0; -} - - -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])) - - -struct name_data { - struct v4l2_standard *std; - unsigned int bcnt; - unsigned int scnt; -}; - -static void name_build(struct name_data *dp,const char *str) -{ - 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; -} - - // 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++; - } + struct v4l2_standard *newstd; + unsigned int std_cnt; + unsigned int idx; - if (amsk) { - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Failed to bucketize the following standards: 0x%llx", - amsk); - } + newstd = pvr2_std_create_enum(&std_cnt,arg); 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 (hdw->video_std_enum_names) { + kfree(hdw->video_std_enum_names); + hdw->video_std_enum_names = 0; + } if (!std_cnt) { pvr2_trace( @@ -1808,42 +1779,22 @@ void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw,int arg) 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++; - } - - // 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; + } else { + hdw->video_std_enum_names = kmalloc(sizeof(char *)*std_cnt, + GFP_KERNEL); + for (idx = 0; idx < std_cnt; idx++) { + hdw->video_std_enum_names[idx] = + newstd[idx].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_info_enum.def.type_enum.value_names = + hdw->video_std_enum_names; + hdw->video_std_info_enum.def.type_enum.count = std_cnt; + hdw->std_defs = newstd; + hdw->std_cnt = std_cnt; } - hdw->video_std_avail = mmsk; + hdw->video_std_avail = arg; 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); @@ -1857,11 +1808,17 @@ unsigned int pvr2_hdw_get_stdenum_count(struct pvr2_hdw *hdw) } -const struct v4l2_standard *pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw, - unsigned int idx) +int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw, + struct v4l2_standard *std, + unsigned int idx) { - if (idx >= hdw->std_cnt) return 0; - return hdw->std_defs + idx; + int ret = -EINVAL; + LOCK_TAKE(hdw->big_lock); do { + if (idx >= hdw->std_cnt) break; + memcpy(std,hdw->std_defs+idx,sizeof(*std)); + ret = 0; + } while (0); LOCK_GIVE(hdw->big_lock); + return ret; } @@ -1895,8 +1852,7 @@ void pvr2_hdw_internal_set_std_cur(struct pvr2_hdw *hdw,int val) // Fix up standard group now hdw->video_std_cur = id; - hdw->controls[PVR2_CID_STDCUR].value = id; - hdw->controls[PVR2_CID_STDCUR].dirty = !0; + hdw->video_std_dirty = !0; for (idx = 0; idx < hdw->std_cnt; idx++) { if (hdw->std_defs[idx].id & id) { hdw->std_id = idx; @@ -1909,42 +1865,6 @@ void pvr2_hdw_internal_set_std_cur(struct pvr2_hdw *hdw,int val) } -static int pvr2_ctl_set_stdcur(struct pvr2_ctrl *cptr,int val) -{ - pvr2_hdw_internal_set_std_cur(cptr->hdw,val); - return 0; -} - - -static int pvr2_ctl_get_stdcur(struct pvr2_ctrl *cptr) -{ - return (int)(cptr->hdw->video_std_cur); -} - - -static int pvr2_ctl_set_stdenumcur(struct pvr2_ctrl *cptr,int val) -{ - if (val < 0) return -EINVAL; - if (val >= cptr->hdw->std_cnt) return -EINVAL; - cptr->hdw->std_id = val; - pvr2_hdw_internal_set_std_cur(cptr->hdw, - cptr->hdw->std_id); - return 0; -} - - -static int pvr2_ctl_get_stdenumcur(struct pvr2_ctrl *cptr) -{ - return cptr->hdw->std_id; -} - - -static int pvr2_ctl_get_stdavail(struct pvr2_ctrl *cptr) -{ - return (int)(cptr->hdw->video_std_avail); -} - - /* Get the number of defined controls */ unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw) { @@ -1956,14 +1876,14 @@ unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw) 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) +/* Retrieve a control handle given its index (0..count-1) */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *hdw, + unsigned int ctl_id) { struct pvr2_ctrl *cptr; unsigned int idx; @@ -1972,212 +1892,38 @@ struct pvr2_ctrl *pvr2_hdw_get_ctrl(struct pvr2_hdw *hdw,unsigned int ctl_id) /* 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; + i = cptr->info->internal_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 (!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 (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 ((cptr->value != value) || (ctlchg != 0)) { - cptr->value = value; - cptr->dirty = !0; - } return 0; } -/* 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; - 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; -} - - -/* Get the current value of the given control. */ -int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr) +/* Given an ID, retrieve the control structure associated with it. */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,unsigned int ctl_id) { - 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; -} - + struct pvr2_ctrl *cptr; + unsigned int idx; + int i; -/* Return the type of the given control (int, enum, or bit mask). */ -int pvr2_ctrl_get_type(struct pvr2_ctrl *cptr) -{ - 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; + /* This could be made a lot more efficient, but for now... */ + for (idx = 0; idx < CTRL_COUNT; idx++) { + cptr = hdw->controls + idx; + i = cptr->info->v4l_id; + if (i && (i == ctl_id)) return cptr; } - return PVR2_CTRL_TYPE_INT; -} - - -/* Return the minimum legal value for a given control. This command is - only relevant for int or enum types. */ -int pvr2_ctrl_get_min_value(struct pvr2_ctrl *cptr) -{ - const struct pvr2_ctl_def *dptr; - if (!cptr) return 0; - dptr = cptr->ctl_def; - return dptr->min_value; -} - - -/* Return the maximum legal value for a given control. This command is - only relevant for int or enum types. */ -int pvr2_ctrl_get_max_value(struct pvr2_ctrl *cptr) -{ - const struct pvr2_ctl_def *dptr; - if (!cptr) return 0; - dptr = cptr->ctl_def; - return dptr->max_value; -} - - -/* Return the default value for a given control. */ -int pvr2_ctrl_get_default_value(struct pvr2_ctrl *cptr) -{ - const struct pvr2_ctl_def *dptr; - if (!cptr) return 0; - dptr = cptr->ctl_def; - return dptr->default_value; -} - - -/* Return a mask of which bits are used within the bit mask of a given - control. This command is only relevant for bit mask types. */ -int pvr2_ctrl_get_mask_value(struct pvr2_ctrl *cptr) -{ - const struct pvr2_ctl_def *dptr; - if (!cptr) return 0; - dptr = cptr->ctl_def; - return dptr->mask_value; -} - - -/* Return true if this is a valid control. */ -int pvr2_ctrl_is_valid(struct pvr2_ctrl *cptr) -{ - if (!cptr) return 0; - return cptr->is_valid; -} - - -/* Return true if the control can be set (otherwise it may only be read, - assuming that it is valid). */ -int pvr2_ctrl_is_writeable(struct pvr2_ctrl *cptr) -{ - const struct pvr2_ctl_def *dptr; - if (!cptr) return 0; - dptr = cptr->ctl_def; - if (!dptr->is_valid) return 0; - if (dptr->set_func) return !0; - if (dptr->get_func) return 0; - return !0; -} - - -/* Return the control's name, or null if there isn't a name or the control - isn't otherwise valid. */ -const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr) -{ - const struct pvr2_ctl_def *dptr; - if (!cptr) return 0; - dptr = cptr->ctl_def; - return dptr->name; -} - - -/* Return the control's description, or null if there isn't a name or the - control isn't otherwise valid. */ -const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr) -{ - const struct pvr2_ctl_def *dptr; - if (!cptr) return 0; - dptr = cptr->ctl_def; - return dptr->desc; + return 0; } -/* 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) +static const char *get_ctrl_typename(enum pvr2_ctl_type tp) { - 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]; + switch (tp) { + case pvr2_ctl_int: return "integer"; + case pvr2_ctl_enum: return "enum"; + case pvr2_ctl_bitmask: return "bitmask"; } - return 0; + return ""; } @@ -2193,64 +1939,33 @@ 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; int commit_flag = 0; - - /* Let's see if the channel changed and we have to update the - frequency because of it. This setup means one can tune the - receiver either by just setting the channel (using the frequency - table), or by directly programming the frequency. How do we - resolve the obvious conflict here? The direct frequency takes - priority; if directly set then we commit that value and force - the channel to zero which is interpreted to mean "none". If on - the other hand we see that the channel has been set and it's a - legal value, then we copy that into the frequency. The metaphor - here is similar to when you tune your digital radio: You an - either set a frequency directly or punch up a pre-programmed - station. Either way a frequency is set, and if you do use a - preset, then the radio also shows you which preset it is - until - you override that by directly entering a new frequency. */ - if (hdw->controls[PVR2_CID_FREQUENCY].dirty) { - /* Frequency has been directly set, so clear out the - channel. */ - hdw->controls[PVR2_CID_CHANNEL].value = 0; - } else if (hdw->controls[PVR2_CID_CHANNEL].dirty) { - int id = hdw->controls[PVR2_CID_CHANNEL].value; - if ((id > 0) && (id <= FREQTABLE_SIZE)) { - if (hdw->controls[PVR2_CID_FREQUENCY].value != - hdw->freqTable[id-1]) { - hdw->controls[PVR2_CID_FREQUENCY].value = - hdw->freqTable[id-1]; - hdw->controls[PVR2_CID_FREQUENCY].dirty = !0; - } - } - } + char buf[100]; + unsigned int bcnt,ccnt; for (idx = 0; idx < CTRL_COUNT; idx++) { cptr = hdw->controls + idx; - if (!cptr->dirty) continue; + if (cptr->info->is_dirty == 0) continue; + if (!cptr->info->is_dirty(cptr)) continue; if (!commit_flag) { commit_flag = !0; } - 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>"; - } - } else { - ctl_value = "<integer>"; - } + + bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ", + cptr->info->name); + value = 0; + cptr->info->get_value(cptr,&value); + pvr2_ctrl_value_to_sym_internal(cptr,~0,value, + buf+bcnt, + sizeof(buf)-bcnt,&ccnt); + bcnt += ccnt; + bcnt += scnprintf(buf+bcnt,sizeof(buf)-bcnt," <%s>", + get_ctrl_typename(cptr->info->type)); pvr2_trace(PVR2_TRACE_CTL, - "/*--TRACE_COMMIT--*/ \"%s\" <-- %d (%s)", - ctl_name,value,ctl_value); + "/*--TRACE_COMMIT--*/ %.*s", + bcnt,buf); } if (!commit_flag) { @@ -2261,7 +1976,7 @@ 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_STDCUR].dirty) { + if (hdw->video_std_dirty) { /* Rewrite the vertical resolution to be appropriate to the video standard that has been selected. */ int nvres; @@ -2270,28 +1985,28 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) } else { nvres = 576; } - if (nvres != hdw->controls[PVR2_CID_VRES].value) { - hdw->controls[PVR2_CID_VRES].value = nvres; - hdw->controls[PVR2_CID_VRES].dirty = !0; + if (nvres != hdw->res_ver_val) { + hdw->res_ver_val = nvres; + hdw->res_ver_dirty = !0; } - if (!hdw->controls[PVR2_CID_INTERLACE].value) { - hdw->controls[PVR2_CID_INTERLACE].value = 0; - hdw->controls[PVR2_CID_INTERLACE].dirty = !0; + if (!hdw->interlace_val) { + hdw->interlace_val = 0; + hdw->interlace_dirty = !0; } } - 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 || - hdw->controls[PVR2_CID_VBR].dirty || - hdw->controls[PVR2_CID_AVERAGEVIDEOBITRATE].dirty || - hdw->controls[PVR2_CID_PEAKVIDEOBITRATE].dirty || - hdw->controls[PVR2_CID_AUDIOBITRATE].dirty || - hdw->controls[PVR2_CID_SRATE].dirty || - hdw->controls[PVR2_CID_AUDIOLAYER].dirty || - hdw->controls[PVR2_CID_AUDIOCRC].dirty || - hdw->controls[PVR2_CID_AUDIOEMPHASIS].dirty) { + if (hdw->video_std_dirty || + hdw->res_ver_dirty || + hdw->res_hor_dirty || + hdw->interlace_dirty || + hdw->vbr_dirty || + hdw->videobitrate_dirty || + hdw->videopeak_dirty || + hdw->audiobitrate_dirty || + hdw->srate_dirty || + hdw->audiolayer_dirty || + hdw->audiocrc_dirty || + hdw->audioemphasis_dirty) { /* If any of this changes, then the encoder needs to be reconfigured, and we need to reset the stream. */ stale_subsys_mask |= PVR2_SUBSYS_ENC_CFG; @@ -2306,7 +2021,8 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) for (idx = 0; idx < CTRL_COUNT; idx++) { cptr = hdw->controls + idx; - cptr->dirty = 0; + if (!cptr->info->clear_dirty) continue; + cptr->info->clear_dirty(cptr); } /* Now execute i2c core update */ @@ -2374,7 +2090,7 @@ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw) unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw) { unsigned int msk = 0; - switch (hdw->controls[PVR2_CID_INPUT].value) { + switch (hdw->input_val) { case PVR2_CVAL_INPUT_TV: case PVR2_CVAL_INPUT_RADIO: if (hdw->decoder_ctrl && @@ -2398,42 +2114,6 @@ unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw) } -static int pvr2_ctl_get_subsys_mask(struct pvr2_ctrl *cptr) -{ - return cptr->hdw->subsys_enabled_mask; -} - - -static int pvr2_ctl_set_subsys_mask(struct pvr2_ctrl *cptr,int val) -{ - pvr2_hdw_subsys_bit_chg_no_lock(cptr->hdw,~0,val); - return 0; -} - - -static int pvr2_ctl_get_subsys_stream_mask(struct pvr2_ctrl *cptr) -{ - return cptr->hdw->subsys_stream_mask; -} - - -static int pvr2_ctl_set_subsys_stream_mask(struct pvr2_ctrl *cptr, - int val) -{ - pvr2_hdw_subsys_stream_bit_chg_no_lock(cptr->hdw,~0,val); - return 0; -} - - -static int pvr2_ctl_get_hsm(struct pvr2_ctrl *cptr) -{ - 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; -} - - int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) { int result; @@ -2449,13 +2129,6 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) } -static int pvr2_ctl_get_signal(struct pvr2_ctrl *cptr) -{ - return ((pvr2_hdw_get_signal_status_internal(cptr->hdw) & - PVR2_SIGNAL_OK) ? 1 : 0); -} - - /* Return bit mask indicating signal status */ unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw) { |