📄 pvrusb2-hdw.c
字号:
hdw->decoder_ctrl->enable( hdw->decoder_ctrl->ctxt,0); } else { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "WARNING:" " No decoder present"); } hdw->subsys_enabled_mask &= ~(1<<PVR2_SUBSYS_B_DIGITIZER_RUN); } if (vmsk & PVR2_SUBSYS_CFG_ALL) { hdw->subsys_enabled_mask &= ~(vmsk & PVR2_SUBSYS_CFG_ALL); } } vmsk = (nmsk ^ hdw->subsys_enabled_mask) & nmsk; if (vmsk) { if (vmsk & (1<<PVR2_SUBSYS_B_ENC_FIRMWARE)) { pvr2_trace(PVR2_TRACE_CTL, "/*---TRACE_CTL----*/" " pvr2_upload_firmware2"); ret = pvr2_upload_firmware2(hdw); if (ret) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Failure uploading encoder" " firmware"); pvr2_hdw_render_useless(hdw); break; } } if (vmsk & (1<<PVR2_SUBSYS_B_ENC_CFG)) { pvr2_trace(PVR2_TRACE_CTL, "/*---TRACE_CTL----*/" " pvr2_encoder_configure"); ret = pvr2_encoder_configure(hdw); if (ret) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Error recovery initiated"); hdw->subsys_enabled_mask &= ~FIRMWARE_RECOVERY_BITS; continue; } } if (vmsk & (1<<PVR2_SUBSYS_B_DIGITIZER_RUN)) { pvr2_trace(PVR2_TRACE_CTL, "/*---TRACE_CTL----*/" " 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 |= (1<<PVR2_SUBSYS_B_DIGITIZER_RUN); } if (vmsk & (1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) { pvr2_trace(PVR2_TRACE_CTL, "/*---TRACE_CTL----*/" " pvr2_hdw_cmd_usbstream(1)"); pvr2_hdw_cmd_usbstream(hdw,!0); } if (vmsk & (1<<PVR2_SUBSYS_B_ENC_RUN)) { pvr2_trace(PVR2_TRACE_CTL, "/*---TRACE_CTL----*/" " pvr2_encoder_start"); ret = pvr2_encoder_start(hdw); if (ret) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Error recovery initiated"); hdw->subsys_enabled_mask &= ~FIRMWARE_RECOVERY_BITS; continue; } } } }}void pvr2_hdw_subsys_bit_chg(struct pvr2_hdw *hdw, unsigned long msk,unsigned long val){ LOCK_TAKE(hdw->big_lock); do { pvr2_hdw_subsys_bit_chg_no_lock(hdw,msk,val); } while (0); LOCK_GIVE(hdw->big_lock);}unsigned long pvr2_hdw_subsys_get(struct pvr2_hdw *hdw){ return hdw->subsys_enabled_mask;}unsigned long pvr2_hdw_subsys_stream_get(struct pvr2_hdw *hdw){ return hdw->subsys_stream_mask;}static void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw, unsigned long msk, unsigned long val){ unsigned long val2; msk &= PVR2_SUBSYS_ALL; val2 = ((hdw->subsys_stream_mask & ~msk) | (val & msk)); pvr2_trace(PVR2_TRACE_INIT, "stream mask changing 0x%lx:0x%lx from 0x%lx to 0x%lx", msk,val,hdw->subsys_stream_mask,val2); hdw->subsys_stream_mask = val2;}void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw, unsigned long msk, unsigned long val){ LOCK_TAKE(hdw->big_lock); do { pvr2_hdw_subsys_stream_bit_chg_no_lock(hdw,msk,val); } while (0); LOCK_GIVE(hdw->big_lock);}static int pvr2_hdw_set_streaming_no_lock(struct pvr2_hdw *hdw,int enableFl){ if ((!enableFl) == !(hdw->flag_streaming_enabled)) return 0; if (enableFl) { pvr2_trace(PVR2_TRACE_START_STOP, "/*--TRACE_STREAM--*/ enable"); pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,~0); } else { pvr2_trace(PVR2_TRACE_START_STOP, "/*--TRACE_STREAM--*/ disable"); pvr2_hdw_subsys_bit_chg_no_lock(hdw,hdw->subsys_stream_mask,0); } if (!hdw->flag_ok) return -EIO; hdw->flag_streaming_enabled = enableFl != 0; return 0;}int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw){ return hdw->flag_streaming_enabled != 0;}int pvr2_hdw_set_streaming(struct pvr2_hdw *hdw,int enable_flag){ int ret; LOCK_TAKE(hdw->big_lock); do { ret = pvr2_hdw_set_streaming_no_lock(hdw,enable_flag); } while (0); LOCK_GIVE(hdw->big_lock); return ret;}static int pvr2_hdw_set_stream_type_no_lock(struct pvr2_hdw *hdw, enum pvr2_config config){ unsigned long sm = hdw->subsys_enabled_mask; if (!hdw->flag_ok) return -EIO; pvr2_hdw_subsys_bit_chg_no_lock(hdw,hdw->subsys_stream_mask,0); hdw->config = config; pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,sm); return 0;}int pvr2_hdw_set_stream_type(struct pvr2_hdw *hdw,enum pvr2_config config){ int ret; if (!hdw->flag_ok) return -EIO; LOCK_TAKE(hdw->big_lock); ret = pvr2_hdw_set_stream_type_no_lock(hdw,config); LOCK_GIVE(hdw->big_lock); return ret;}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 v4l2_std_id get_default_standard(struct pvr2_hdw *hdw){ int unit_number = hdw->unit_number; int tp = 0; if ((unit_number >= 0) && (unit_number < PVR_NUM)) { tp = video_std[unit_number]; } return tp;}static unsigned int get_default_error_tolerance(struct pvr2_hdw *hdw){ int unit_number = hdw->unit_number; int tp = 0; if ((unit_number >= 0) && (unit_number < PVR_NUM)) { tp = tolerance[unit_number]; } return tp;}static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw){ /* Try a harmless request to fetch the eeprom's address over endpoint 1. See what happens. Only the full FX2 image can respond to this. If this probe fails then likely the FX2 firmware needs be loaded. */ int result; LOCK_TAKE(hdw->ctl_lock); do { hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR; result = pvr2_send_request_ex(hdw,HZ*1,!0, hdw->cmd_buffer,1, hdw->cmd_buffer,1); if (result < 0) break; } while(0); LOCK_GIVE(hdw->ctl_lock); if (result) { pvr2_trace(PVR2_TRACE_INIT, "Probe of device endpoint 1 result status %d", result); } else { pvr2_trace(PVR2_TRACE_INIT, "Probe of device endpoint 1 succeeded"); } return result == 0;}struct pvr2_std_hack { v4l2_std_id pat; /* Pattern to match */ v4l2_std_id msk; /* Which bits we care about */ v4l2_std_id std; /* What additional standards or default to set */};/* This data structure labels specific combinations of standards from tveeprom that we'll try to recognize. If we recognize one, then assume a specified default standard to use. This is here because tveeprom only tells us about available standards not the intended default standard (if any) for the device in question. We guess the default based on what has been reported as available. Note that this is only for guessing a default - which can always be overridden explicitly - and if the user has otherwise named a default then that default will always be used in place of this table. */const static struct pvr2_std_hack std_eeprom_maps[] = { { /* PAL(B/G) */ .pat = V4L2_STD_B|V4L2_STD_GH, .std = V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_PAL_G, }, { /* NTSC(M) */ .pat = V4L2_STD_MN, .std = V4L2_STD_NTSC_M, }, { /* PAL(I) */ .pat = V4L2_STD_PAL_I, .std = V4L2_STD_PAL_I, }, { /* SECAM(L/L') */ .pat = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC, .std = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC, }, { /* PAL(D/D1/K) */ .pat = V4L2_STD_DK, .std = V4L2_STD_PAL_D/V4L2_STD_PAL_D1|V4L2_STD_PAL_K, },};static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw){ char buf[40]; unsigned int bcnt; v4l2_std_id std1,std2; std1 = get_default_standard(hdw); bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom); pvr2_trace(PVR2_TRACE_STD, "Supported video standard(s) reported by eeprom: %.*s", bcnt,buf); hdw->std_mask_avail = hdw->std_mask_eeprom; std2 = std1 & ~hdw->std_mask_avail; if (std2) { bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std2); pvr2_trace(PVR2_TRACE_STD, "Expanding supported video standards" " to include: %.*s", bcnt,buf); hdw->std_mask_avail |= std2; } pvr2_hdw_internal_set_std_avail(hdw); if (std1) { bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std1); pvr2_trace(PVR2_TRACE_STD, "Initial video standard forced to %.*s", bcnt,buf); hdw->std_mask_cur = std1; hdw->std_dirty = !0; pvr2_hdw_internal_find_stdenum(hdw); return; } { unsigned int idx; for (idx = 0; idx < ARRAY_SIZE(std_eeprom_maps); idx++) { if (std_eeprom_maps[idx].msk ? ((std_eeprom_maps[idx].pat ^ hdw->std_mask_eeprom) & std_eeprom_maps[idx].msk) : (std_eeprom_maps[idx].pat != hdw->std_mask_eeprom)) continue; bcnt = pvr2_std_id_to_str(buf,sizeof(buf), std_eeprom_maps[idx].std); pvr2_trace(PVR2_TRACE_STD, "Initial video standard guessed as %.*s", bcnt,buf); hdw->std_mask_cur = std_eeprom_maps[idx].std; hdw->std_dirty = !0; pvr2_hdw_internal_find_stdenum(hdw); return; } } if (hdw->std_enum_cnt > 1) { // Autoselect the first listed standard hdw->std_enum_cur = 1; hdw->std_mask_cur = hdw->std_defs[hdw->std_enum_cur-1].id; hdw->std_dirty = !0; pvr2_trace(PVR2_TRACE_STD, "Initial video standard auto-selected to %s", hdw->std_defs[hdw->std_enum_cur-1].name); return; } pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Unable to select a viable initial video standard");}static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw){ int ret; unsigned int idx; struct pvr2_ctrl *cptr; int reloadFl = 0; if ((hdw->hdw_type == PVR2_HDW_TYPE_29XXX) || (hdw->hdw_type == PVR2_HDW_TYPE_24XXX)) { if (!reloadFl) { reloadFl = (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints == 0); if (reloadFl) { pvr2_trace(PVR2_TRACE_INIT, "USB endpoint config looks strange" "; possibly firmware needs to be" " loaded"); } } if (!reloadFl) { reloadFl = !pvr2_hdw_check_firmware(hdw); if (reloadFl) { pvr2_trace(PVR2_TRACE_INIT, "Check for FX2 firmware failed" "; possibly firmware needs to be" " loaded"); } } if (reloadFl) { if (pvr2_upload_firmware1(hdw) != 0) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Failure uploading firmware1"); } return; } } hdw->fw1_state = FW1_STATE_OK; if (initusbreset) { pvr2_hdw_device_reset(hdw); } if (!pvr2_hdw_dev_ok(hdw)) return; if (hdw->hdw_type < ARRAY_SIZE(pvr2_client_lists)) { for (idx = 0; idx < pvr2_client_lists[hdw->hdw_type].cnt; idx++) { request_module( pvr2_client_lists[hdw->hdw_type].lst[idx]); } } if ((hdw->hdw_type == PVR2_HDW_TYPE_29XXX) || (hdw->hdw_type == PVR2_HDW_TYPE_24XXX)) { pvr2_hdw_cmd_powerup(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; if (pvr2_upload_firmware2(hdw)){ pvr2_trace(PVR2_TRACE_ERROR_LEGS,"device unstable!!"); pvr2_hdw_render_useless(hdw); return; } } // This step MUST happen after the earlier powerup step. pvr2_i2c_core_init(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; for (idx = 0; idx < CTRLDEF_COUNT; idx++) { cptr = hdw->controls + idx; if (cptr->info->skip_init) continue; if (!cptr->info->set_value) continue; cptr->info->set_value(cptr,~0,cptr->info->default_value); } /* Set up special default values for the television and radio frequencies here. It's not really important what these defaults are, but I set them to something usable in the Chicago area just to make driver testing a little easier. */ /* US Broadcast channel 7 (175.25 MHz) */ hdw->freqValTelevision = 175250000L; /* 104.3 MHz, a usable FM station for my area */ hdw->freqValRadio = 104300000L; // Do not use pvr2_reset_ctl_endpoints() here. It is not // thread-safe against the normal pvr2_send_request() mechanism. // (We should make it thread safe). ret = pvr2_hdw_get_eeprom_addr(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; if (ret < 0) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Unable to determine location of eeprom, skipping"); } else { hdw->eeprom_addr = ret; pvr2_eeprom_analyze(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; } pvr2_hdw_setup_std(hdw); if (!get_default_tuner_type(hdw)) { pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_setup: Tuner type overridden to %d", hdw->tuner_type); } hdw->tuner_updated = !0; pvr2_i2c_core_check_stale(hdw); hdw->tuner_updated = 0; if (!pvr2_hdw_dev_ok(hdw)) return; pvr2_hdw_commit_ctl_internal(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; hdw->vid_stream = pvr2_stream_create(); if (!pvr2_hdw_dev_ok(hdw)) return; pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_setup: video stream is %p",hdw->vid_stream); if (hdw->vid_stream) { idx = get_default_error_tolerance(hdw); if (idx) { pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_setup: video stream %p" " setting tolerance %u", hdw->vid_stream,idx);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -