diff options
Diffstat (limited to 'v4l_experimental/pvrusb2/pvrusb2-hdw.c')
-rw-r--r-- | v4l_experimental/pvrusb2/pvrusb2-hdw.c | 252 |
1 files changed, 115 insertions, 137 deletions
diff --git a/v4l_experimental/pvrusb2/pvrusb2-hdw.c b/v4l_experimental/pvrusb2/pvrusb2-hdw.c index 234617d31..bde8cdfca 100644 --- a/v4l_experimental/pvrusb2/pvrusb2-hdw.c +++ b/v4l_experimental/pvrusb2/pvrusb2-hdw.c @@ -1,6 +1,6 @@ /* * - * $Id: pvrusb2-hdw.c,v 1.5 2005/12/02 13:59:00 mcisely Exp $ + * $Id: pvrusb2-hdw.c,v 1.6 2006/01/01 08:26:03 mcisely Exp $ * * Copyright (C) 2005 Mike Isely <isely@pobox.com> * @@ -28,12 +28,10 @@ #include "pvrusb2.h" #include "pvrusb2-util.h" #include "pvrusb2-hdw.h" -#include "pvrusb2-i2c.h" +#include "pvrusb2-i2c-core.h" #include "pvrusb2-tuner.h" #include "pvrusb2-eeprom.h" #include "pvrusb2-hdw-internal.h" -#include "pvrusb2-audio.h" -#include "pvrusb2-video.h" #include "pvrusb2-encoder.h" #include "pvrusb2-debug.h" @@ -44,6 +42,7 @@ static int hfull = 1; static int width = 720; static int initusbreset = 1; static int procreload = 0; +static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 }; module_param(initusbreset, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(initusbreset, "Do USB reset device on probe"); @@ -54,6 +53,8 @@ module_param(hfull, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(hfull, "full height video ?"); module_param(width, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(width, "video width : 720,480,352"); +module_param_array(tuner, int, NULL, 0444); +MODULE_PARM_DESC(tuner,"specify installed tuner type"); #define PVR2_CTL_WRITE_ENDPOINT 0x01 #define PVR2_CTL_READ_ENDPOINT 0x81 @@ -703,8 +704,17 @@ void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw, if (vmsk & PVR2_SUBSYS_DIGITIZER_RUN) { pvr2_trace(PVR2_TRACE_CTL, "/*---TRACE_CTL----*/" - " pvr2_decoder_disable_output"); - pvr2_decoder_disable_output(hdw->dcp); + " decoder disable"); + if (hdw->decoder_ctrl) { + hdw->decoder_ctrl->enable( + hdw->decoder_ctrl->ctxt,0); + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "WARNING:" + " No decoder present"); + } + hdw->subsys_enabled_mask &= + ~PVR2_SUBSYS_DIGITIZER_RUN; } if (vmsk & PVR2_SUBSYS_CFG_ALL) { hdw->subsys_enabled_mask &= @@ -726,66 +736,6 @@ void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw, break; } } - if (vmsk & PVR2_SUBSYS_TUNER_CFG_STD) { - pvr2_trace(PVR2_TRACE_CTL, - "/*---TRACE_CTL----*/" - " pvr2_tuner_set_standard"); - pvr2_tuner_set_standard(hdw); - } - if (vmsk & PVR2_SUBSYS_TUNER_CFG_FREQ) { - pvr2_trace(PVR2_TRACE_CTL, - "/*---TRACE_CTL----*/" - " pvr2_tuner_set_freq"); - pvr2_tuner_set_freq(hdw); - } - if (vmsk & PVR2_SUBSYS_AUDIO_CFG_STD) { - pvr2_trace(PVR2_TRACE_CTL, - "/*---TRACE_CTL----*/" - " pvr2_audio_set_standard"); - pvr2_audio_set_standard(hdw); - } - if (vmsk & PVR2_SUBSYS_AUDIO_CFG_MODE) { - pvr2_trace(PVR2_TRACE_CTL, - "/*---TRACE_CTL----*/" - " pvr2_audio_set_stereo"); - pvr2_audio_set_stereo(hdw); - } - if (vmsk & PVR2_SUBSYS_AUDIO_CFG_VBBTM) { - pvr2_trace(PVR2_TRACE_CTL, - "/*---TRACE_CTL----*/" - " pvr2_audio_setvolume"); - pvr2_audio_setvolume(hdw); - } - if (vmsk & PVR2_SUBSYS_DIGITIZER_CFG_NORM) { - pvr2_trace(PVR2_TRACE_CTL, - "/*---TRACE_CTL----*/" - " pvr2_decoder_set_norm"); - pvr2_decoder_set_norm(hdw->dcp); - } - if (vmsk & PVR2_SUBSYS_DIGITIZER_CFG_INPUT) { - pvr2_trace(PVR2_TRACE_CTL, - "/*---TRACE_CTL----*/" - " pvr2_decoder_set_input"); - pvr2_decoder_set_input(hdw->dcp); - } - if (vmsk & PVR2_SUBSYS_DIGITIZER_CFG_SIZE) { - pvr2_trace(PVR2_TRACE_CTL, - "/*---TRACE_CTL----*/" - " pvr2_decoder_set_size"); - pvr2_decoder_set_size(hdw->dcp); - } - if (vmsk & PVR2_SUBSYS_DIGITIZER_CFG_AUDIO) { - pvr2_trace(PVR2_TRACE_CTL, - "/*---TRACE_CTL----*/" - " pvr2_decoder_set_audio"); - pvr2_decoder_set_audio(hdw->dcp); - } - if (vmsk & PVR2_SUBSYS_DIGITIZER_CFG_BCSH) { - pvr2_trace(PVR2_TRACE_CTL, - "/*---TRACE_CTL----*/" - " pvr2_decoder_set_bcsh"); - pvr2_decoder_set_bcsh(hdw->dcp); - } if (vmsk & PVR2_SUBSYS_ENC_CFG) { pvr2_trace(PVR2_TRACE_CTL, "/*---TRACE_CTL----*/" @@ -802,8 +752,17 @@ void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw, if (vmsk & PVR2_SUBSYS_DIGITIZER_RUN) { pvr2_trace(PVR2_TRACE_CTL, "/*---TRACE_CTL----*/" - " pvr2_decoder_enable_output"); - pvr2_decoder_enable_output(hdw->dcp); + " decoder enable"); + if (hdw->decoder_ctrl) { + hdw->decoder_ctrl->enable( + hdw->decoder_ctrl->ctxt,!0); + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "WARNING:" + " No decoder present"); + } + hdw->subsys_enabled_mask |= + PVR2_SUBSYS_DIGITIZER_RUN; } if (vmsk & PVR2_SUBSYS_USBSTREAM_RUN) { pvr2_trace(PVR2_TRACE_CTL, @@ -949,6 +908,19 @@ int pvr2_hdw_set_stream_type(struct pvr2_hdw *hdw,enum pvr2_config config) } +static int get_default_tuner_type(struct pvr2_hdw *hdw) +{ + int unit_number = hdw->unit_number; + int tp = -1; + if ((unit_number >= 0) && (unit_number < PVR_NUM)) { + tp = tuner[unit_number]; + } + if (tp < 0) return -EINVAL; + hdw->tuner_type = tp; + return 0; +} + + static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) { unsigned int idx; @@ -965,7 +937,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) } if (!pvr2_hdw_dev_ok(hdw)) return; - pvr2_i2c_init(hdw); + pvr2_i2c_core_init(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; if (pvr2_upload_firmware2(hdw)){ @@ -983,18 +955,19 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) pvr2_reset_ctl_endpoints(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; - hdw->dcp = pvr2_decoder_create(hdw); - pvr2_eeprom_analyze(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; - if (!pvr2_tuner_get_default_type(hdw)) { + if (!get_default_tuner_type(hdw)) { pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_setup: Tuner type overridden to %d", hdw->tuner_type); } - pvr2_tuner_set_type(hdw); + hdw->tuner_updated = !0; + pvr2_i2c_core_check_stale(hdw); + hdw->tuner_updated = 0; + if (!pvr2_hdw_dev_ok(hdw)) return; pvr2_eeprom_set_default_standard(hdw); @@ -1013,6 +986,12 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) } if (!pvr2_hdw_dev_ok(hdw)) return; + + /* Make sure everything is up to date */ + pvr2_i2c_core_sync(hdw); + + if (!pvr2_hdw_dev_ok(hdw)) return; + hdw->flag_init_ok = !0; } @@ -1188,9 +1167,13 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) pvr2_stream_destroy(hdw->vid_stream); hdw->vid_stream = 0; } - pvr2_decoder_destroy(hdw->dcp); - hdw->dcp = 0; - pvr2_i2c_done(hdw); + if (hdw->audio_stat) { + hdw->audio_stat->detach(hdw->audio_stat->ctxt); + } + if (hdw->decoder_ctrl) { + hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt); + } + pvr2_i2c_core_done(hdw); pvr2_hdw_remove_usb_stuff(hdw); down(&pvr2_unit_sem); do { if ((hdw->unit_number >= 0) && @@ -1380,13 +1363,12 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) 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 this. 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. */ + 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. */ @@ -1460,29 +1442,6 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) } } - if (hdw->controls[PVR2_CID_VIDEOSTANDARD].dirty) { - hdw->controls[PVR2_CID_FREQUENCY].dirty = !0; - stale_subsys_mask |= (PVR2_SUBSYS_DIGITIZER_CFG_NORM | - PVR2_SUBSYS_TUNER_CFG_STD | - PVR2_SUBSYS_AUDIO_CFG_STD); - } - - if (hdw->controls[PVR2_CID_HRES].dirty || - hdw->controls[PVR2_CID_VRES].dirty) { - stale_subsys_mask |= PVR2_SUBSYS_DIGITIZER_CFG_SIZE; - } - - if (hdw->controls[PVR2_CID_BRIGHTNESS].dirty || - hdw->controls[PVR2_CID_CONTRAST].dirty || - hdw->controls[PVR2_CID_SATURATION].dirty || - hdw->controls[PVR2_CID_HUE].dirty) { - stale_subsys_mask |= PVR2_SUBSYS_DIGITIZER_CFG_BCSH; - } - - if (hdw->controls[PVR2_CID_SRATE].dirty) { - stale_subsys_mask |= PVR2_SUBSYS_DIGITIZER_CFG_AUDIO; - } - if (hdw->controls[PVR2_CID_VIDEOSTANDARD].dirty || hdw->controls[PVR2_CID_VRES].dirty || hdw->controls[PVR2_CID_HRES].dirty || @@ -1495,43 +1454,25 @@ int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) hdw->controls[PVR2_CID_AUDIOLAYER].dirty || hdw->controls[PVR2_CID_AUDIOCRC].dirty || hdw->controls[PVR2_CID_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; - } - - if (hdw->controls[PVR2_CID_AUDIOMODE].dirty || - hdw->controls[PVR2_CID_INPUT].dirty) { - stale_subsys_mask |= PVR2_SUBSYS_AUDIO_CFG_MODE; - } - - if (hdw->controls[PVR2_CID_VOLUME].dirty || - hdw->controls[PVR2_CID_BALANCE].dirty || - hdw->controls[PVR2_CID_BASS].dirty || - hdw->controls[PVR2_CID_TREBLE].dirty || - hdw->controls[PVR2_CID_MUTE].dirty) { - stale_subsys_mask |= PVR2_SUBSYS_AUDIO_CFG_VBBTM; - } - - if (hdw->controls[PVR2_CID_INPUT].dirty) { - stale_subsys_mask |= PVR2_SUBSYS_DIGITIZER_CFG_INPUT; - } - - if (hdw->controls[PVR2_CID_FREQUENCY].dirty) { - stale_subsys_mask |= PVR2_SUBSYS_TUNER_CFG_FREQ; - } - - if (stale_subsys_mask & (PVR2_SUBSYS_DIGITIZER_CFG_NORM | - PVR2_SUBSYS_TUNER_CFG_STD | - PVR2_SUBSYS_AUDIO_CFG_STD | - PVR2_SUBSYS_DIGITIZER_CFG_SIZE | - PVR2_SUBSYS_DIGITIZER_CFG_AUDIO | - PVR2_SUBSYS_ENC_CFG)) { stale_subsys_mask |= hdw->subsys_stream_mask; } + /* Scan i2c core at this point - before we clear all the dirty + bits. Various parts of the i2c core will notice dirty bits as + appropriate and arrange to broadcast or directly send updates to + the client drivers in order to keep everything in sync */ + pvr2_i2c_core_check_stale(hdw); + for (idx = 0; idx < PVR2_CID_COUNT; idx++) { hdw->controls[idx].dirty = 0; } + /* Now execute i2c core update */ + pvr2_i2c_core_sync(hdw); + pvr2_hdw_subsys_bit_chg_no_lock(hdw,stale_subsys_mask,0); pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,saved_subsys_mask); @@ -1548,6 +1489,41 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw) } +void pvr2_hdw_poll(struct pvr2_hdw *hdw) +{ + LOCK_TAKE(hdw->big_lock); do { + pvr2_i2c_core_sync(hdw); + } while (0); LOCK_GIVE(hdw->big_lock); +} + + +void pvr2_hdw_setup_poll_trigger(struct pvr2_hdw *hdw, + void (*func)(void *), + void *data) +{ + LOCK_TAKE(hdw->big_lock); do { + hdw->poll_trigger_func = func; + hdw->poll_trigger_data = data; + } while (0); LOCK_GIVE(hdw->big_lock); +} + + +void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *hdw) +{ + if (hdw->poll_trigger_func) { + hdw->poll_trigger_func(hdw->poll_trigger_data); + } +} + + +void pvr2_hdw_poll_trigger(struct pvr2_hdw *hdw) +{ + LOCK_TAKE(hdw->big_lock); do { + pvr2_hdw_poll_trigger_unlocked(hdw); + } while (0); LOCK_GIVE(hdw->big_lock); +} + + /* 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) @@ -1563,9 +1539,11 @@ unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw) switch (hdw->controls[PVR2_CID_INPUT].value) { case PVR2_CVAL_INPUT_TV: case PVR2_CVAL_INPUT_RADIO: - if (pvr2_decoder_is_tuned(hdw->dcp) > 0) { + if (hdw->decoder_ctrl && + hdw->decoder_ctrl->tuned(hdw->decoder_ctrl->ctxt)) { msk |= PVR2_SIGNAL_OK; - if (pvr2_audio_update_status(hdw) == 0) { + if (hdw->audio_stat && + hdw->audio_stat->status(hdw->audio_stat->ctxt)) { if (hdw->flag_stereo) { msk |= PVR2_SIGNAL_STEREO; } |