/* This defines a minimum interval that the decoder must remain quiet
before we are allowed to start it running. */ #define TIME_MSEC_DECODER_WAIT 50
/* This defines a minimum interval that the decoder must be allowed to run
before we can safely begin using its streaming output. */ #define TIME_MSEC_DECODER_STABILIZATION_WAIT 300
/* This defines a minimum interval that the encoder must remain quiet
before we are allowed to configure it. */ #define TIME_MSEC_ENCODER_WAIT 50
/* This defines the minimum interval that the encoder must successfully run beforeweconsiderthattheencoderhasrunatleastoncesinceits firmwarehasbeenloaded.Thismeasurementisinimportantforcases wherewecan'tdosomethinguntilweknowthattheencoderhasbeenrun
at least once. */ #define TIME_MSEC_ENCODER_OK 250
/* US Broadcast channel 3 (61.25 MHz), to help with testing */ staticint default_tv_freq = 61250000L; /* 104.3 MHz, a usable FM station for my area */ staticint default_radio_freq = 104300000L;
module_param_named(tv_freq, default_tv_freq, int, 0444);
MODULE_PARM_DESC(tv_freq, "specify initial television frequency");
module_param_named(radio_freq, default_radio_freq, int, 0444);
MODULE_PARM_DESC(radio_freq, "specify initial radio frequency");
staticint ctrl_get_cropcapbl(struct pvr2_ctrl *cptr, int *val)
{ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { return stat;
}
*val = cap->bounds.left; return0;
}
staticint ctrl_get_cropcapbt(struct pvr2_ctrl *cptr, int *val)
{ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { return stat;
}
*val = cap->bounds.top; return0;
}
staticint ctrl_get_cropcapbw(struct pvr2_ctrl *cptr, int *val)
{ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { return stat;
}
*val = cap->bounds.width; return0;
}
staticint ctrl_get_cropcapbh(struct pvr2_ctrl *cptr, int *val)
{ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { return stat;
}
*val = cap->bounds.height; return0;
}
staticint ctrl_get_cropcapdl(struct pvr2_ctrl *cptr, int *val)
{ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { return stat;
}
*val = cap->defrect.left; return0;
}
staticint ctrl_get_cropcapdt(struct pvr2_ctrl *cptr, int *val)
{ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { return stat;
}
*val = cap->defrect.top; return0;
}
staticint ctrl_get_cropcapdw(struct pvr2_ctrl *cptr, int *val)
{ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { return stat;
}
*val = cap->defrect.width; return0;
}
staticint ctrl_get_cropcapdh(struct pvr2_ctrl *cptr, int *val)
{ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { return stat;
}
*val = cap->defrect.height; return0;
}
staticint ctrl_get_cropcappan(struct pvr2_ctrl *cptr, int *val)
{ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { return stat;
}
*val = cap->pixelaspect.numerator; return0;
}
staticint ctrl_get_cropcappad(struct pvr2_ctrl *cptr, int *val)
{ struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; int stat = pvr2_hdw_check_cropcap(cptr->hdw); if (stat != 0) { return stat;
}
*val = cap->pixelaspect.denominator; return0;
}
staticint ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
{ /* Actual maximum depends on the video standard in effect. */ if (cptr->hdw->std_mask_cur & V4L2_STD_525_60) {
*vp = 480;
} else {
*vp = 576;
} return0;
}
staticint ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp)
{ /* Actual minimum depends on device digitizer type. */ if (cptr->hdw->hdw_desc->flag_has_cx25840) {
*vp = 75;
} else {
*vp = 17;
} return0;
}
/* Set the currently tuned frequency and account for all possible
driver-core side effects of this action. */ staticvoid pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsignedlong val)
{ if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { if (hdw->freqSelector) { /* Swing over to radio frequency selection */
hdw->freqSelector = 0;
hdw->freqDirty = !0;
} if (hdw->freqValRadio != val) {
hdw->freqValRadio = val;
hdw->freqSlotRadio = 0;
hdw->freqDirty = !0;
}
} else { if (!(hdw->freqSelector)) { /* Swing over to television frequency selection */
hdw->freqSelector = 1;
hdw->freqDirty = !0;
} if (hdw->freqValTelevision != val) {
hdw->freqValTelevision = val;
hdw->freqSlotTelevision = 0;
hdw->freqDirty = !0;
}
}
}
int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw)
{ return hdw->unit_number;
}
/* Attempt to locate one of the given set of files. Messages are logged appropriatetowhathasbeenfound.Thereturnvaluewillbe0or greateronsuccess(itwillbetheindexofthefilenamefound)and fw_entrywillbefilledin.Otherwiseanegativeerrorisreturnedon failure.Ifthereturnvalueis-ENOENTthennoviablefirmwarefile
could be located. */ staticint pvr2_locate_firmware(struct pvr2_hdw *hdw, conststruct firmware **fw_entry, constchar *fwtypename, unsignedint fwcount, constchar *fwnames[])
{ unsignedint idx; int ret = -EINVAL; for (idx = 0; idx < fwcount; idx++) {
ret = request_firmware(fw_entry,
fwnames[idx],
&hdw->usb_dev->dev); if (!ret) {
trace_firmware("Located %s firmware: %s; uploading...",
fwtypename,
fwnames[idx]); return idx;
} if (ret == -ENOENT) continue;
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "request_firmware fatal error with code=%d",ret); return ret;
}
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "***WARNING*** Device %s firmware seems to be missing.",
fwtypename);
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Did you install the pvrusb2 firmware files in their proper location?"); if (fwcount == 1) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "request_firmware unable to locate %s file %s",
fwtypename,fwnames[0]);
} else {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "request_firmware unable to locate one of the following %s files:",
fwtypename); for (idx = 0; idx < fwcount; idx++) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "request_firmware: Failed to find %s",
fwnames[idx]);
}
} return ret;
}
if (!hdw->hdw_desc->fx2_firmware.cnt) {
hdw->fw1_state = FW1_STATE_OK;
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Connected device type defines no firmware to upload; ignoring firmware"); return -ENOTTY;
}
hdw->fw1_state = FW1_STATE_FAILED; // default result
trace_firmware("pvr2_upload_firmware1");
ret = pvr2_locate_firmware(hdw,&fw_entry,"fx2 controller",
hdw->hdw_desc->fx2_firmware.cnt,
hdw->hdw_desc->fx2_firmware.lst); if (ret < 0) { if (ret == -ENOENT) hdw->fw1_state = FW1_STATE_MISSING; return ret;
}
int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
{ conststruct firmware *fw_entry = NULL; void *fw_ptr; unsignedint pipe, fw_len, fw_done, bcnt, icnt; int actual_length; int ret = 0; int fwidx; staticconstchar *fw_files[] = {
CX2341X_FIRM_ENC_FILENAME,
};
if (hdw->hdw_desc->flag_skip_cx23416_firmware) { return0;
}
trace_firmware("pvr2_upload_firmware2");
ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder",
ARRAY_SIZE(fw_files), fw_files); if (ret < 0) return ret;
fwidx = ret;
ret = 0; /* Since we're about to completely reinitialize the encoder, invalidateourcachedcopyofitsconfigurationstate.Next
time we configure the encoder, then we'll fully configure it. */
hdw->enc_cur_valid = 0;
/* Encoder is about to be reset so note that as far as we're
concerned now, the encoder has never been run. */
timer_delete_sync(&hdw->encoder_run_timer); if (hdw->state_encoder_runok) {
hdw->state_encoder_runok = 0;
trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
}
/* First prepare firmware loading */
ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/
ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/
ret |= pvr2_hdw_cmd_deep_reset(hdw);
ret |= pvr2_write_register(hdw, 0xa064, 0x00000000); /*APU command*/
ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000408); /*gpio dir*/
ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/
ret |= pvr2_write_register(hdw, 0x9058, 0xffffffed); /*VPU ctrl*/
ret |= pvr2_write_register(hdw, 0x9054, 0xfffffffd); /*reset hw blocks*/
ret |= pvr2_write_register(hdw, 0x07f8, 0x80000800); /*encoder SDRAM refresh*/
ret |= pvr2_write_register(hdw, 0x07fc, 0x0000001a); /*encoder SDRAM pre-charge*/
ret |= pvr2_write_register(hdw, 0x0700, 0x00000000); /*I2C clock*/
ret |= pvr2_write_register(hdw, 0xaa00, 0x00000000); /*unknown*/
ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/
ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/
ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_FWPOST1);
ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
if (fw_len % sizeof(u32)) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "size of %s firmware must be a multiple of %zu bytes",
fw_files[fwidx],sizeof(u32));
release_firmware(fw_entry);
ret = -EINVAL; goto done;
}
fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL); if (fw_ptr == NULL){
release_firmware(fw_entry);
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "failed to allocate memory for firmware2 upload");
ret = -ENOMEM; goto done;
}
fw_done = 0; for (fw_done = 0; fw_done < fw_len;) {
bcnt = fw_len - fw_done; if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE;
memcpy(fw_ptr, fw_entry->data + fw_done, bcnt); /* Usbsnoop log shows that we must swap bytes... */ /* Some background info: The data being swapped here is a firmwareimagedestinedforthempegencoderchipthat livesattheotherendofaUSBendpoint.Theencoder chipalwaystalksin32bitchunksanditsstorageis organizedinto32bitwords.Howeverfromthefile systemtotheencoderchipeverythingispurelyabyte stream.Thefirmwarefile'scontentsarealways32bit swappedfromwhattheencoderexpects.Thustheneed alwaysexiststoswapthebytesregardlessoftheendian typeofthehostprocessorandthereforeswab32()makes
the most sense. */ for (icnt = 0; icnt < bcnt/4 ; icnt++)
((u32 *)fw_ptr)[icnt] = swab32(((u32 *)fw_ptr)[icnt]);
ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt,
&actual_length, 1000);
ret |= (actual_length != bcnt); if (ret) break;
fw_done += bcnt;
}
trace_firmware("upload of %s : %i / %i ",
fw_files[fwidx],fw_done,fw_len);
kfree(fw_ptr);
release_firmware(fw_entry);
if (ret) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "firmware2 upload transfer failure"); goto done;
}
/* Finish upload */
ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/
ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/
ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
if (ret) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "firmware2 upload post-proc failure");
}
done: if (hdw->hdw_desc->signal_routing_scheme ==
PVR2_ROUTING_SCHEME_GOTVIEW) { /* Ensure that GPIO 11 is set to output for GOTVIEW
hardware. */
pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
} return ret;
}
staticint pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl)
{ /* Even though we really only care about the video decoder chip at thispoint,we'llbroadcaststreamon/offtoallsub-devices anyway,justincasesomebodyelsewantstohearthe
command... */
pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 stream=%s",
(enablefl ? "on" : "off"));
v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl);
v4l2_device_call_all(&hdw->v4l2_dev, 0, audio, s_stream, enablefl); if (hdw->decoder_client_id) { /* We get here if the encoder has been noticed. Otherwise we'llissueawarningtotheuser(whichshould
normally never happen). */ return0;
} if (!hdw->flag_decoder_missed) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "***WARNING*** No decoder present");
hdw->flag_decoder_missed = !0;
trace_stbit("flag_decoder_missed",
hdw->flag_decoder_missed);
} return -EIO;
}
int pvr2_hdw_get_state(struct pvr2_hdw *hdw)
{ return hdw->master_state;
}
int pvr2_hdw_untrip(struct pvr2_hdw *hdw)
{ int fl;
LOCK_TAKE(hdw->big_lock); do {
fl = pvr2_hdw_untrip_unlocked(hdw);
} while (0); LOCK_GIVE(hdw->big_lock); if (fl) pvr2_hdw_state_sched(hdw); return0;
}
int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw)
{ return hdw->state_pipeline_req != 0;
}
int pvr2_hdw_set_streaming(struct pvr2_hdw *hdw,int enable_flag)
{ int ret,st;
LOCK_TAKE(hdw->big_lock);
pvr2_hdw_untrip_unlocked(hdw); if (!enable_flag != !hdw->state_pipeline_req) {
hdw->state_pipeline_req = enable_flag != 0;
pvr2_trace(PVR2_TRACE_START_STOP, "/*--TRACE_STREAM--*/ %s",
enable_flag ? "enable" : "disable");
}
pvr2_hdw_state_sched(hdw);
LOCK_GIVE(hdw->big_lock); if ((ret = pvr2_hdw_wait(hdw,0)) < 0) return ret; if (enable_flag) { while ((st = hdw->master_state) != PVR2_STATE_RUN) { if (st != PVR2_STATE_READY) return -EIO; if ((ret = pvr2_hdw_wait(hdw,st)) < 0) return ret;
}
} return0;
}
int pvr2_hdw_set_stream_type(struct pvr2_hdw *hdw,enum pvr2_config config)
{ int fl;
LOCK_TAKE(hdw->big_lock); if ((fl = (hdw->desired_stream_type != config)) != 0) {
hdw->desired_stream_type = config;
hdw->state_pipeline_config = 0;
trace_stbit("state_pipeline_config",
hdw->state_pipeline_config);
pvr2_hdw_state_sched(hdw);
}
LOCK_GIVE(hdw->big_lock); if (fl) return0; return pvr2_hdw_wait(hdw,0);
}
staticint 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;
hdw->tuner_updated = !0; return0;
}
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]; if (tp) return tp;
} return0;
}
staticunsignedint 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;
}
staticint pvr2_hdw_check_firmware(struct pvr2_hdw *hdw)
{ /* Try a harmless request to fetch the eeprom's address over endpoint1.Seewhathappens.OnlythefullFX2imagecan respondtothis.IfthisprobefailsthenlikelytheFX2
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 */
};
bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom);
pvr2_trace(PVR2_TRACE_STD, "Supported video standard(s) reported available in hardware: %.*s",
bcnt,buf);
hdw->std_mask_avail = hdw->std_mask_eeprom;
std2 = (std1|std3) & ~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;
}
mid = cd->module_id;
fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL; if (!fname) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Module ID %u for device %s has no name? The driver might have a configuration problem.",
mid,
hdw->hdw_desc->description); return -EINVAL;
}
pvr2_trace(PVR2_TRACE_INIT, "Module ID %u (%s) for device %s being loaded...",
mid, fname,
hdw->hdw_desc->description);
i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list,
ARRAY_SIZE(i2caddr)); if (!i2ccnt && ((p = (mid < ARRAY_SIZE(module_i2c_addresses)) ?
module_i2c_addresses[mid] : NULL) != NULL)) { /* Second chance: Try default i2c address list */
i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, p,
ARRAY_SIZE(i2caddr)); if (i2ccnt) {
pvr2_trace(PVR2_TRACE_INIT, "Module ID %u: Using default i2c address list",
mid);
}
}
if (!i2ccnt) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Module ID %u (%s) for device %s: No i2c addresses. The driver might have a configuration problem.",
mid, fname, hdw->hdw_desc->description); return -EINVAL;
}
if (i2ccnt == 1) {
pvr2_trace(PVR2_TRACE_INIT, "Module ID %u: Setting up with specified i2c address 0x%x",
mid, i2caddr[0]);
sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap,
fname, i2caddr[0], NULL);
} else {
pvr2_trace(PVR2_TRACE_INIT, "Module ID %u: Setting up with address probe list",
mid);
sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap,
fname, 0, i2caddr);
}
if (!sd) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Module ID %u (%s) for device %s failed to load. Possible missing sub-device kernel module or initialization failure within module.",
mid, fname, hdw->hdw_desc->description); return -EIO;
}
/* Tag this sub-device instance with the module ID we know about. Inotherplaceswe'llusethattagtodetermineiftheinstance
requires special handling. */
sd->grp_id = mid;
cm = &hdw->hdw_desc->client_modules; for (idx = 0; idx < cm->cnt; idx++) {
request_module(cm->lst[idx]);
}
ct = &hdw->hdw_desc->client_table; for (idx = 0; idx < ct->cnt; idx++) { if (pvr2_hdw_load_subdev(hdw, &ct->lst[idx]) < 0) okFl = 0;
} if (!okFl) {
hdw->flag_modulefail = !0;
pvr2_hdw_render_useless(hdw);
}
}
staticvoid pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
{ int ret; unsignedint idx; struct pvr2_ctrl *cptr; int reloadFl = 0; if (hdw->hdw_desc->fx2_firmware.cnt) { 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 (!pvr2_hdw_dev_ok(hdw)) return;
hdw->force_dirty = !0;
if (!hdw->hdw_desc->flag_no_powerup) {
pvr2_hdw_cmd_powerup(hdw); if (!pvr2_hdw_dev_ok(hdw)) return;
}
/* Take the IR chip out of reset, if appropriate */ if (hdw->ir_scheme_active == PVR2_IR_SCHEME_ZILOG) {
pvr2_issue_simple_cmd(hdw,
FX2CMD_HCW_ZILOG_RESET |
(1 << 8) |
((0) << 16));
}
/* This step MUST happen after the earlier powerup step */
pvr2_i2c_core_init(hdw); if (!pvr2_hdw_dev_ok(hdw)) return;
/* Reset demod only on Hauppauge 160xxx platform */ if (le16_to_cpu(hdw->usb_dev->descriptor.idVendor) == 0x2040 &&
(le16_to_cpu(hdw->usb_dev->descriptor.idProduct) == 0x7502 ||
le16_to_cpu(hdw->usb_dev->descriptor.idProduct) == 0x7510)) {
pr_info("%s(): resetting 160xxx demod\n", __func__); /* TODO: not sure this is proper place to reset once only */
pvr2_issue_simple_cmd(hdw,
FX2CMD_HCW_DEMOD_RESET_PIN |
(1 << 8) |
((0) << 16));
usleep_range(10000, 10500);
pvr2_issue_simple_cmd(hdw,
FX2CMD_HCW_DEMOD_RESET_PIN |
(1 << 8) |
((1) << 16));
usleep_range(10000, 10500);
}
pvr2_hdw_load_modules(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);
}
pvr2_hdw_cx25840_vbi_hack(hdw);
/* Set up special default values for the television and radio frequencieshere.It'snotreallyimportantwhatthesedefaults are,butIsetthemtosomethingusableintheChicagoareajust
to make driver testing a little easier. */
// 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).
if (hdw->hdw_desc->flag_has_hauppauge_rom) {
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;
}
} else {
hdw->tuner_type = hdw->hdw_desc->default_tuner_type;
hdw->tuner_updated = !0;
hdw->std_mask_eeprom = V4L2_STD_ALL;
}
if (!get_default_tuner_type(hdw)) {
pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_setup: Tuner type overridden to %d",
hdw->tuner_type);
}
if (!pvr2_hdw_dev_ok(hdw)) return;
if (hdw->hdw_desc->signal_routing_scheme ==
PVR2_ROUTING_SCHEME_GOTVIEW) { /* Ensure that GPIO 11 is set to output for GOTVIEW
hardware. */
pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
}
pvr2_hdw_commit_setup(hdw);
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);
}
pvr2_stream_setup(hdw->vid_stream,hdw->usb_dev,
PVR2_VID_ENDPOINT,idx);
}
if (!pvr2_hdw_dev_ok(hdw)) return;
hdw->flag_init_ok = !0;
pvr2_hdw_state_sched(hdw);
}
/* Set up the structure and attempt to put the device into a usable state. Thiscanbeatime-consumingoperation,whichiswhyitisnotdone
internally as part of the create() step. */ staticvoid pvr2_hdw_setup(struct pvr2_hdw *hdw)
{
pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) begin",hdw); do {
pvr2_hdw_setup_low(hdw);
pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_setup(hdw=%p) done, ok=%d init_ok=%d",
hdw,pvr2_hdw_dev_ok(hdw),hdw->flag_init_ok); if (pvr2_hdw_dev_ok(hdw)) { if (hdw->flag_init_ok) {
pvr2_trace(
PVR2_TRACE_INFO, "Device initialization completed successfully."); break;
} if (hdw->fw1_state == FW1_STATE_RELOAD) {
pvr2_trace(
PVR2_TRACE_INFO, "Device microcontroller firmware (re)loaded; it should now reset and reconnect."); break;
}
pvr2_trace(
PVR2_TRACE_ERROR_LEGS, "Device initialization was not successful."); if (hdw->fw1_state == FW1_STATE_MISSING) {
pvr2_trace(
PVR2_TRACE_ERROR_LEGS, "Giving up since device microcontroller firmware appears to be missing."); break;
}
} if (hdw->flag_modulefail) {
pvr2_trace(
PVR2_TRACE_ERROR_LEGS, "***WARNING*** pvrusb2 driver initialization failed due to the failure of one or more sub-device kernel modules.");
pvr2_trace(
PVR2_TRACE_ERROR_LEGS, "You need to resolve the failing condition before this driver can function. There should be some earlier messages giving more information about the problem."); break;
} if (procreload) {
pvr2_trace(
PVR2_TRACE_ERROR_LEGS, "Attempting pvrusb2 recovery by reloading primary firmware.");
pvr2_trace(
PVR2_TRACE_ERROR_LEGS, "If this works, device should disconnect and reconnect in a sane state.");
hdw->fw1_state = FW1_STATE_UNKNOWN;
pvr2_upload_firmware1(hdw);
} else {
pvr2_trace(
PVR2_TRACE_ERROR_LEGS, "***WARNING*** pvrusb2 device hardware appears to be jammed and I can't clear it.");
pvr2_trace(
PVR2_TRACE_ERROR_LEGS, "You might need to power cycle the pvrusb2 device in order to recover.");
}
} while (0);
pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) end",hdw);
}
/* Perform second stage initialization. Set callback pointer first so that wecanavoidapossibleinitializationrace(ifthekernelthreadruns
before the callback has been set). */ int pvr2_hdw_initialize(struct pvr2_hdw *hdw, void (*callback_func)(void *), void *callback_data)
{
LOCK_TAKE(hdw->big_lock); do { if (hdw->flag_disconnected) { /* Handle a race here: If we're already disconnectedbythispoint,thengiveup.Ifwe getpastthisthenwe'llremainconnectedfor thedurationofinitializationsincetheentire initializationsequenceisnowprotectedbythe
big_lock. */ break;
}
hdw->state_data = callback_data;
hdw->state_func = callback_func;
pvr2_hdw_setup(hdw);
} while (0); LOCK_GIVE(hdw->big_lock); return hdw->flag_init_ok;
}
/* Create, set up, and return a structure for interacting with the
underlying hardware. */ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, conststruct usb_device_id *devid)
{ unsignedint idx,cnt1,cnt2,m; struct pvr2_hdw *hdw = NULL; int valid_std_mask; struct pvr2_ctrl *cptr; struct usb_device *usb_dev; conststruct pvr2_device_desc *hdw_desc;
__u8 ifnum; struct v4l2_queryctrl qctrl; struct pvr2_ctl_info *ciptr;
if (hdw_desc == NULL) {
pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_create: No device description pointer, unable to continue.");
pvr2_trace(PVR2_TRACE_INIT, "If you have a new device type, please contact Mike Isely <isely@pobox.com> to get it included in the driver"); goto fail;
}
hdw = kzalloc(sizeof(*hdw),GFP_KERNEL);
pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"",
hdw,hdw_desc->description);
pvr2_trace(PVR2_TRACE_INFO, "Hardware description: %s",
hdw_desc->description); if (hdw_desc->flag_is_experimental) {
pvr2_trace(PVR2_TRACE_INFO, "**********");
pvr2_trace(PVR2_TRACE_INFO, "***WARNING*** Support for this device (%s) is experimental.",
hdw_desc->description);
pvr2_trace(PVR2_TRACE_INFO, "Important functionality might not be entirely working.");
pvr2_trace(PVR2_TRACE_INFO, "Please consider contacting the driver author to help with further stabilization of the driver.");
pvr2_trace(PVR2_TRACE_INFO, "**********");
} if (!hdw) goto fail;
/* Calculate which inputs are OK */
m = 0; if (hdw_desc->flag_has_analogtuner) m |= 1 << PVR2_CVAL_INPUT_TV; if (hdw_desc->digital_control_scheme != PVR2_DIGITAL_SCHEME_NONE) {
m |= 1 << PVR2_CVAL_INPUT_DTV;
} if (hdw_desc->flag_has_svideo) m |= 1 << PVR2_CVAL_INPUT_SVIDEO; if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE; if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO;
hdw->input_avail_mask = m;
hdw->input_allowed_mask = hdw->input_avail_mask;
/* If not a hybrid device, pathway_state never changes. So
initialize it here to what it should forever be. */ if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_DTV))) {
hdw->pathway_state = PVR2_PATHWAY_ANALOG;
} elseif (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_TV))) {
hdw->pathway_state = PVR2_PATHWAY_DIGITAL;
}
/* Remove _all_ associations between this driver and the underlying USB
layer. */ staticvoid pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw)
{ if (hdw->flag_disconnected) return;
pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_remove_usb_stuff: hdw=%p",hdw); if (hdw->ctl_read_urb) {
usb_kill_urb(hdw->ctl_read_urb);
usb_free_urb(hdw->ctl_read_urb);
hdw->ctl_read_urb = NULL;
} if (hdw->ctl_write_urb) {
usb_kill_urb(hdw->ctl_write_urb);
usb_free_urb(hdw->ctl_write_urb);
hdw->ctl_write_urb = NULL;
} if (hdw->ctl_read_buffer) {
kfree(hdw->ctl_read_buffer);
hdw->ctl_read_buffer = NULL;
} if (hdw->ctl_write_buffer) {
kfree(hdw->ctl_write_buffer);
hdw->ctl_write_buffer = NULL;
}
hdw->flag_disconnected = !0; /* If we don't do this, then there will be a dangling struct device referencetoourdisappearingdevicepersistinginsidetheV4L
core... */
v4l2_device_disconnect(&hdw->v4l2_dev);
hdw->usb_dev = NULL;
hdw->usb_intf = NULL;
pvr2_hdw_render_useless(hdw);
}
int pvr2_hdw_dev_ok(struct pvr2_hdw *hdw)
{ return (hdw && hdw->flag_ok);
}
/* Called when hardware has been unplugged */ void pvr2_hdw_disconnect(struct pvr2_hdw *hdw)
{
pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_disconnect(hdw=%p)",hdw);
LOCK_TAKE(hdw->big_lock);
pvr2_i2c_core_done(hdw);
LOCK_TAKE(hdw->ctl_lock);
pvr2_hdw_remove_usb_stuff(hdw);
LOCK_GIVE(hdw->ctl_lock);
LOCK_GIVE(hdw->big_lock);
}
/* Get the number of defined controls */ unsignedint pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw)
{ return hdw->control_cnt;
}
/* Retrieve a control handle given its index (0..count-1) */ struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *hdw, unsignedint idx)
{ if (idx >= hdw->control_cnt) return NULL; return hdw->controls + idx;
}
/* Retrieve a control handle given its index (0..count-1) */ struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *hdw, unsignedint ctl_id)
{ struct pvr2_ctrl *cptr; unsignedint idx; int i;
/* This could be made a lot more efficient, but for now... */ for (idx = 0; idx < hdw->control_cnt; idx++) {
cptr = hdw->controls + idx;
i = cptr->info->internal_id; if (i && (i == ctl_id)) return cptr;
} return NULL;
}
/* Given a V4L ID, retrieve the control structure associated with it. */ struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,unsignedint ctl_id)
{ struct pvr2_ctrl *cptr; unsignedint idx; int i;
/* This could be made a lot more efficient, but for now... */ for (idx = 0; idx < hdw->control_cnt; idx++) {
cptr = hdw->controls + idx;
i = cptr->info->v4l_id; if (i && (i == ctl_id)) return cptr;
} return NULL;
}
/* Given a V4L ID for its immediate predecessor, retrieve the control
structure associated with it. */ struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *hdw, unsignedint ctl_id)
{ struct pvr2_ctrl *cptr,*cp2; unsignedint idx; int i;
/* This could be made a lot more efficient, but for now... */
cp2 = NULL; for (idx = 0; idx < hdw->control_cnt; idx++) {
cptr = hdw->controls + idx;
i = cptr->info->v4l_id; if (!i) continue; if (i <= ctl_id) continue; if (cp2 && (cp2->info->v4l_id < i)) continue;
cp2 = cptr;
} return cp2; return NULL;
}
staticconstchar *get_ctrl_typename(enum pvr2_ctl_type tp)
{ switch (tp) { case pvr2_ctl_int: return"integer"; case pvr2_ctl_enum: return"enum"; case pvr2_ctl_bool: return"boolean"; case pvr2_ctl_bitmask: return"bitmask";
} return"";
}
staticvoid pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id, constchar *name, int val)
{ struct v4l2_control ctrl; struct v4l2_subdev *sd;
/* Execute whatever commands are required to update the state of all the
sub-devices so that they match our current control values. */ staticvoid pvr2_subdev_update(struct pvr2_hdw *hdw)
{ struct v4l2_subdev *sd; unsignedint id;
pvr2_subdev_update_func fp;
if (hdw->srate_dirty || hdw->force_dirty) {
u32 val;
pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d",
hdw->srate_val); switch (hdw->srate_val) { default: case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
val = 48000; break; case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
val = 44100; break; case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
val = 32000; break;
}
v4l2_device_call_all(&hdw->v4l2_dev, 0,
audio, s_clock_freq, val);
}
/* Unable to set crop parameters; there is apparently no equivalent
for VIDIOC_S_CROP */
v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
id = sd->grp_id; if (id >= ARRAY_SIZE(pvr2_module_update_functions)) continue;
fp = pvr2_module_update_functions[id]; if (!fp) continue;
(*fp)(hdw, sd);
}
if (hdw->tuner_signal_stale || hdw->cropcap_stale) {
pvr2_hdw_status_poll(hdw);
}
}
/* Figure out if we need to commit control changes. If so, mark internal stateflagstoindicatethisfactandreturntrue.Otherwisedonothing
else and return false. */ staticint pvr2_hdw_commit_setup(struct pvr2_hdw *hdw)
{ unsignedint idx; struct pvr2_ctrl *cptr; int value; int commit_flag = hdw->force_dirty; char buf[100]; unsignedint bcnt,ccnt;
for (idx = 0; idx < hdw->control_cnt; idx++) {
cptr = hdw->controls + idx; if (!cptr->info->is_dirty) continue; if (!cptr->info->is_dirty(cptr)) continue;
commit_flag = !0;
/* Perform all operations needed to commit all control changes. This must beperformedinsynchronizationwiththepipelinestateandisthus expectedtobecalledaspartofthedriver'sworkerthread.Return trueifcommitsuccessful,otherwisereturnfalsetoindicatethat
commit isn't possible at this time. */ staticint pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
{ unsignedint idx; struct pvr2_ctrl *cptr; int disruptive_change;
if (hdw->input_dirty && hdw->state_pathway_ok &&
(((hdw->input_val == PVR2_CVAL_INPUT_DTV) ?
PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG) !=
hdw->pathway_state)) { /* Change of mode being asked for... */
hdw->state_pathway_ok = 0;
trace_stbit("state_pathway_ok", hdw->state_pathway_ok);
} if (!hdw->state_pathway_ok) { /* Can't commit anything until pathway is ok. */ return0;
}
/* Handle some required side effects when the video standard is
changed.... */ if (hdw->std_dirty) { int nvres; int gop_size; if (hdw->std_mask_cur & V4L2_STD_525_60) {
nvres = 480;
gop_size = 15;
} else {
nvres = 576;
gop_size = 12;
} /* Rewrite the vertical resolution to be appropriate to the
video standard that has been selected. */ if (nvres != hdw->res_ver_val) {
hdw->res_ver_val = nvres;
hdw->res_ver_dirty = !0;
} /* Rewrite the GOP size to be appropriate to the video
standard that has been selected. */ if (gop_size != hdw->enc_ctl_state.video_gop_size) { struct v4l2_ext_controls cs; struct v4l2_ext_control c1;
memset(&cs, 0, sizeof(cs));
memset(&c1, 0, sizeof(c1));
cs.controls = &c1;
cs.count = 1;
c1.id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
c1.value = gop_size;
cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,
VIDIOC_S_EXT_CTRLS);
}
}
/* The broadcast decoder can only scale down, so if *res_*_dirty&&cropwindow<outputformat==>enlargecrop. * *Thempegencoderreceivesfieldsofres_hor_valdotsand *res_ver_valhalflines.Limits:hor<=720,ver<=576.
*/ if (hdw->res_hor_dirty && hdw->cropw_val < hdw->res_hor_val) {
hdw->cropw_val = hdw->res_hor_val;
hdw->cropw_dirty = !0;
} elseif (hdw->cropw_dirty) {
hdw->res_hor_dirty = !0; /* must rescale */
hdw->res_hor_val = min(720, hdw->cropw_val);
} if (hdw->res_ver_dirty && hdw->croph_val < hdw->res_ver_val) {
hdw->croph_val = hdw->res_ver_val;
hdw->croph_dirty = !0;
} elseif (hdw->croph_dirty) { int nvres = hdw->std_mask_cur & V4L2_STD_525_60 ? 480 : 576;
hdw->res_ver_dirty = !0;
hdw->res_ver_val = min(nvres, hdw->croph_val);
}
/* If any of the below has changed, then we can't do the update whilethepipelineisrunning.Pipelinemustbepausedfirst anddecoder->encoderconnectionbemadequiescentbeforewe
can proceed. */
disruptive_change =
(hdw->std_dirty ||
hdw->enc_unsafe_stale ||
hdw->srate_dirty ||
hdw->res_ver_dirty ||
hdw->res_hor_dirty ||
hdw->cropw_dirty ||
hdw->croph_dirty ||
hdw->input_dirty ||
(hdw->active_stream_type != hdw->desired_stream_type)); if (disruptive_change && !hdw->state_pipeline_idle) { /* Pipeline is not idle; we can't proceed. Arrange to causepipelinetostopsothatwecantrythisagain
later.... */
hdw->state_pipeline_pause = !0; return0;
}
if (hdw->srate_dirty) { /* Write new sample rate into control structure since *themastercopyisstale.Wemusttracksrate *separatefromthempegcontrolstructurebecause
* other logic also uses this value. */ struct v4l2_ext_controls cs; struct v4l2_ext_control c1;
memset(&cs,0,sizeof(cs));
memset(&c1,0,sizeof(c1));
cs.controls = &c1;
cs.count = 1;
c1.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ;
c1.value = hdw->srate_val;
cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,VIDIOC_S_EXT_CTRLS);
}
if (hdw->active_stream_type != hdw->desired_stream_type) { /* Handle any side effects of stream config here */
hdw->active_stream_type = hdw->desired_stream_type;
}
if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) &&
hdw->state_encoder_run) { /* If encoder isn't running or it can't be touched, then thiswillgetworkedoutlaterwhenwestartthe
encoder. */ if (pvr2_encoder_adjust(hdw) < 0) return !0;
}
hdw->state_pipeline_config = !0; /* Hardware state may have changed in a way to cause the cropping capabilitiestohavechanged.Somarkitstale,whichwill
cause a later re-fetch. */
trace_stbit("state_pipeline_config",hdw->state_pipeline_config); return !0;
}
int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw)
{ int fl;
LOCK_TAKE(hdw->big_lock);
fl = pvr2_hdw_commit_setup(hdw);
LOCK_GIVE(hdw->big_lock); if (!fl) return0; return pvr2_hdw_wait(hdw,0);
}
staticvoid pvr2_hdw_worker_poll(struct work_struct *work)
{ int fl = 0; struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,workpoll);
LOCK_TAKE(hdw->big_lock); do {
fl = pvr2_hdw_state_eval(hdw);
} while (0); LOCK_GIVE(hdw->big_lock); if (fl && hdw->state_func) {
hdw->state_func(hdw->state_data);
}
}
int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
{ int result;
LOCK_TAKE(hdw->ctl_lock); do {
hdw->cmd_buffer[0] = FX2CMD_GET_USB_SPEED;
result = pvr2_send_request(hdw,
hdw->cmd_buffer,1,
hdw->cmd_buffer,1); if (result < 0) break;
result = (hdw->cmd_buffer[0] != 0);
} while(0); LOCK_GIVE(hdw->ctl_lock); return result;
}
/* Execute poll of tuner status */ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw)
{
LOCK_TAKE(hdw->big_lock); do {
pvr2_hdw_status_poll(hdw);
} while (0); LOCK_GIVE(hdw->big_lock);
}
staticint pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw)
{ if (!hdw->cropcap_stale) { return0;
}
pvr2_hdw_status_poll(hdw); if (hdw->cropcap_stale) { return -EIO;
} return0;
}
/* Return information about cropping capabilities */ int pvr2_hdw_get_cropcap(struct pvr2_hdw *hdw, struct v4l2_cropcap *pp)
{ int stat = 0;
LOCK_TAKE(hdw->big_lock);
stat = pvr2_hdw_check_cropcap(hdw); if (!stat) {
memcpy(pp, &hdw->cropcap_info, sizeof(hdw->cropcap_info));
}
LOCK_GIVE(hdw->big_lock); return stat;
}
/* Return information about the tuner */ int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp)
{
LOCK_TAKE(hdw->big_lock); do { if (hdw->tuner_signal_stale) {
pvr2_hdw_status_poll(hdw);
}
memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner));
} while (0);
LOCK_GIVE(hdw->big_lock); return0;
}
/* Get handle to video output stream */ struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *hp)
{ return hp->vid_stream;
}
void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw)
{ int nr = pvr2_hdw_get_unit_number(hdw);
LOCK_TAKE(hdw->big_lock); do {
pr_info("pvrusb2: ================= START STATUS CARD #%d =================\n", nr);
v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status);
pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:");
cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2");
pvr2_hdw_state_log_state(hdw);
pr_info("pvrusb2: ================== END STATUS CARD #%d ==================\n", nr);
} while (0);
LOCK_GIVE(hdw->big_lock);
}
/* Grab EEPROM contents, needed for direct method. */ #define EEPROM_SIZE 8192 #define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__) static u8 *pvr2_full_eeprom_fetch(struct pvr2_hdw *hdw)
{ struct i2c_msg msg[2];
u8 *eeprom;
u8 iadd[2];
u8 addr;
u16 eepromSize; unsignedint offs; int ret; int mode16 = 0; unsigned pcnt,tcnt;
eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); if (!eeprom) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Failed to allocate memory required to read eeprom"); return NULL;
}
trace_eeprom("Value for eeprom addr from controller was 0x%x",
hdw->eeprom_addr);
addr = hdw->eeprom_addr; /* Seems that if the high bit is set, then the *real* eeprom addressisshiftedrightnowbitposition(noticedthisin
newer PVR USB2 hardware) */ if (addr & 0x80) addr >>= 1;
/* FX2 documentation states that a 16bit-addressed eeprom is expectediftheI2Caddressisanoddnumber(yeah,thisis
strange but it's what they do) */
mode16 = (addr & 1);
eepromSize = (mode16 ? EEPROM_SIZE : 256);
trace_eeprom("Examining %d byte eeprom at location 0x%x using %d bit addressing",
eepromSize, addr,
mode16 ? 16 : 8);
/* We have to do the actual eeprom data fetch ourselves, because (1)we'reonlyfetchingpartoftheeeprom,and(2)ifwewere gettingthewholethingourI2Cdrivercan'tgrabitinone
pass - which is what tveeprom is otherwise going to attempt */ for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) {
pcnt = 16; if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt;
offs = tcnt + (eepromSize - EEPROM_SIZE); if (mode16) {
iadd[0] = offs >> 8;
iadd[1] = offs;
} else {
iadd[0] = offs;
}
msg[1].len = pcnt;
msg[1].buf = eeprom+tcnt; if ((ret = i2c_transfer(&hdw->i2c_adap,
msg,ARRAY_SIZE(msg))) != 2) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "eeprom fetch set offs err=%d",ret);
kfree(eeprom); return NULL;
}
} return eeprom;
}
void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int mode, int enable_flag)
{ int ret;
u16 address; unsignedint pipe;
LOCK_TAKE(hdw->big_lock); do { if ((hdw->fw_buffer == NULL) == !enable_flag) break;
if (!enable_flag) {
pvr2_trace(PVR2_TRACE_FIRMWARE, "Cleaning up after CPU firmware fetch");
kfree(hdw->fw_buffer);
hdw->fw_buffer = NULL;
hdw->fw_size = 0; if (hdw->fw_cpu_flag) { /* Now release the CPU. It will disconnect
and reconnect later. */
pvr2_hdw_cpureset_assert(hdw,0);
} break;
}
hdw->fw_cpu_flag = (mode != 2); if (hdw->fw_cpu_flag) {
hdw->fw_size = (mode == 1) ? 0x4000 : 0x2000;
pvr2_trace(PVR2_TRACE_FIRMWARE, "Preparing to suck out CPU firmware (size=%u)",
hdw->fw_size);
hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL); if (!hdw->fw_buffer) {
hdw->fw_size = 0; break;
}
/* We have to hold the CPU during firmware upload. */
pvr2_hdw_cpureset_assert(hdw,1);
/* download the firmware from address 0000-1fff in 2048
(=0x800) bytes chunk. */
pvr2_trace(PVR2_TRACE_FIRMWARE, "Done grabbing CPU firmware");
} else {
pvr2_trace(PVR2_TRACE_FIRMWARE, "Sucking down EEPROM contents");
hdw->fw_buffer = pvr2_full_eeprom_fetch(hdw); if (!hdw->fw_buffer) {
pvr2_trace(PVR2_TRACE_FIRMWARE, "EEPROM content suck failed."); break;
}
hdw->fw_size = EEPROM_SIZE;
pvr2_trace(PVR2_TRACE_FIRMWARE, "Done sucking down EEPROM contents");
}
} while (0);
LOCK_GIVE(hdw->big_lock);
}
/* Return true if we're in a mode for retrieval CPU firmware */ int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *hdw)
{ return hdw->fw_buffer != NULL;
}
int pvr2_hdw_cpufw_get(struct pvr2_hdw *hdw,unsignedint offs, char *buf,unsignedint cnt)
{ int ret = -EINVAL;
LOCK_TAKE(hdw->big_lock); do { if (!buf) break; if (!cnt) break;
if (!hdw->fw_buffer) {
ret = -EIO; break;
}
if (offs >= hdw->fw_size) {
pvr2_trace(PVR2_TRACE_FIRMWARE, "Read firmware data offs=%d EOF",
offs);
ret = 0; break;
}
if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
hdw->ctl_timeout_flag = !0; if (hdw->ctl_write_pend_flag)
usb_unlink_urb(hdw->ctl_write_urb); if (hdw->ctl_read_pend_flag)
usb_unlink_urb(hdw->ctl_read_urb);
}
}
/* Issue a command and get a response from the device. This extended versionincludesaprobeflag(whichifsetmeansthatdeviceerrors shouldnotbeloggedortreatedasfatal)andatimeoutinjiffies.
This can be used to non-lethally probe the health of endpoint 1. */ staticint pvr2_send_request_ex(struct pvr2_hdw *hdw, unsignedint timeout,int probe_fl, void *write_data,unsignedint write_len, void *read_data,unsignedint read_len)
{ unsignedint idx; int status = 0; struct hdw_timer timer = {
.hdw = hdw,
};
if (!hdw->ctl_lock_held) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Attempted to execute control transfer without lock!!"); return -EDEADLK;
} if (!hdw->flag_ok && !probe_fl) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Attempted to execute control transfer when device not ok"); return -EIO;
} if (!(hdw->ctl_read_urb && hdw->ctl_write_urb)) { if (!probe_fl) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Attempted to execute control transfer when USB is disconnected");
} return -ENOTTY;
}
/* Ensure that we have sane parameters */ if (!write_data) write_len = 0; if (!read_data) read_len = 0; if (write_len > PVR2_CTL_BUFFSIZE) {
pvr2_trace(
PVR2_TRACE_ERROR_LEGS, "Attempted to execute %d byte control-write transfer (limit=%d)",
write_len,PVR2_CTL_BUFFSIZE); return -EINVAL;
} if (read_len > PVR2_CTL_BUFFSIZE) {
pvr2_trace(
PVR2_TRACE_ERROR_LEGS, "Attempted to execute %d byte control-read transfer (limit=%d)",
write_len,PVR2_CTL_BUFFSIZE); return -EINVAL;
} if ((!write_len) && (!read_len)) {
pvr2_trace(
PVR2_TRACE_ERROR_LEGS, "Attempted to execute null control transfer?"); return -EINVAL;
}
if (write_len && write_data) {
hdw->cmd_debug_state = 2; /* Transfer write data to internal buffer */ for (idx = 0; idx < write_len; idx++) {
hdw->ctl_write_buffer[idx] =
((unsignedchar *)write_data)[idx];
} /* Initiate a write request */
usb_fill_bulk_urb(hdw->ctl_write_urb,
hdw->usb_dev,
usb_sndbulkpipe(hdw->usb_dev,
PVR2_CTL_WRITE_ENDPOINT),
hdw->ctl_write_buffer,
write_len,
pvr2_ctl_write_complete,
hdw);
hdw->ctl_write_urb->actual_length = 0;
hdw->ctl_write_pend_flag = !0; if (usb_urb_ep_type_check(hdw->ctl_write_urb)) {
pvr2_trace(
PVR2_TRACE_ERROR_LEGS, "Invalid write control endpoint"); return -EINVAL;
}
status = usb_submit_urb(hdw->ctl_write_urb,GFP_KERNEL); if (status < 0) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Failed to submit write-control URB status=%d",
status);
hdw->ctl_write_pend_flag = 0; goto done;
}
}
if (read_len) {
hdw->cmd_debug_state = 3;
memset(hdw->ctl_read_buffer,0x43,read_len); /* Initiate a read request */
usb_fill_bulk_urb(hdw->ctl_read_urb,
hdw->usb_dev,
usb_rcvbulkpipe(hdw->usb_dev,
PVR2_CTL_READ_ENDPOINT),
hdw->ctl_read_buffer,
read_len,
pvr2_ctl_read_complete,
hdw);
hdw->ctl_read_urb->actual_length = 0;
hdw->ctl_read_pend_flag = !0; if (usb_urb_ep_type_check(hdw->ctl_read_urb)) {
pvr2_trace(
PVR2_TRACE_ERROR_LEGS, "Invalid read control endpoint"); return -EINVAL;
}
status = usb_submit_urb(hdw->ctl_read_urb,GFP_KERNEL); if (status < 0) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Failed to submit read-control URB status=%d",
status);
hdw->ctl_read_pend_flag = 0; goto done;
}
}
/* Start timer */
add_timer(&timer.timer);
/* Now wait for all I/O to complete */
hdw->cmd_debug_state = 4; while (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
wait_for_completion(&hdw->ctl_done);
}
hdw->cmd_debug_state = 5;
/* Stop timer */
timer_delete_sync(&timer.timer);
hdw->cmd_debug_state = 6;
status = 0;
if (hdw->ctl_timeout_flag) {
status = -ETIMEDOUT; if (!probe_fl) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Timed out control-write");
} goto done;
}
if (write_len) { /* Validate results of write request */ if ((hdw->ctl_write_urb->status != 0) &&
(hdw->ctl_write_urb->status != -ENOENT) &&
(hdw->ctl_write_urb->status != -ESHUTDOWN) &&
(hdw->ctl_write_urb->status != -ECONNRESET)) { /* USB subsystem is reporting some kind of failure
on the write */
status = hdw->ctl_write_urb->status; if (!probe_fl) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "control-write URB failure, status=%d",
status);
} goto done;
} if (hdw->ctl_write_urb->actual_length < write_len) { /* Failed to write enough data */
status = -EIO; if (!probe_fl) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "control-write URB short, expected=%d got=%d",
write_len,
hdw->ctl_write_urb->actual_length);
} goto done;
}
} if (read_len && read_data) { /* Validate results of read request */ if ((hdw->ctl_read_urb->status != 0) &&
(hdw->ctl_read_urb->status != -ENOENT) &&
(hdw->ctl_read_urb->status != -ESHUTDOWN) &&
(hdw->ctl_read_urb->status != -ECONNRESET)) { /* USB subsystem is reporting some kind of failure
on the read */
status = hdw->ctl_read_urb->status; if (!probe_fl) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "control-read URB failure, status=%d",
status);
} goto done;
} if (hdw->ctl_read_urb->actual_length < read_len) { /* Failed to read enough data */
status = -EIO; if (!probe_fl) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "control-read URB short, expected=%d got=%d",
read_len,
hdw->ctl_read_urb->actual_length);
} goto done;
} /* Transfer retrieved data out from internal buffer */ for (idx = 0; idx < read_len; idx++) {
((unsignedchar *)read_data)[idx] =
hdw->ctl_read_buffer[idx];
}
}
ret |= pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 4);
*data = PVR2_COMPOSE_LE(hdw->cmd_buffer,0);
LOCK_GIVE(hdw->ctl_lock);
return ret;
}
void pvr2_hdw_render_useless(struct pvr2_hdw *hdw)
{ if (!hdw->flag_ok) return;
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Device being rendered inoperable"); if (hdw->vid_stream) {
pvr2_stream_setup(hdw->vid_stream,NULL,0,0);
}
hdw->flag_ok = 0;
trace_stbit("flag_ok",hdw->flag_ok);
pvr2_hdw_state_sched(hdw);
}
void pvr2_hdw_device_reset(struct pvr2_hdw *hdw)
{ int ret;
pvr2_trace(PVR2_TRACE_INIT,"Performing a device reset...");
ret = usb_lock_device_for_reset(hdw->usb_dev,NULL); if (ret == 0) {
ret = usb_reset_device(hdw->usb_dev);
usb_unlock_device(hdw->usb_dev);
} else {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Failed to lock USB device ret=%d",ret);
} if (init_pause_msec) {
pvr2_trace(PVR2_TRACE_INFO, "Waiting %u msec for hardware to settle",
init_pause_msec);
msleep(init_pause_msec);
}
/* Write the CPUCS register on the 8051. The lsb of the register
is the reset bit; a 1 asserts reset while a 0 clears it. */
pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,1000); if (ret < 0) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "cpureset_assert(%d) error=%d",val,ret);
pvr2_hdw_render_useless(hdw);
}
kfree(da);
}
int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw)
{ return pvr2_issue_simple_cmd(hdw,FX2CMD_DEEP_RESET);
}
int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
{ return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_ON);
}
int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
{
pvr2_trace(PVR2_TRACE_INIT, "Requesting decoder reset"); if (hdw->decoder_client_id) {
v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
core, reset, 0);
pvr2_hdw_cx25840_vbi_hack(hdw); return0;
}
pvr2_trace(PVR2_TRACE_INIT, "Unable to reset decoder: nothing attached"); return -ENOTTY;
}
staticint pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff)
{
hdw->flag_ok = !0;
/* Use this for Hauppauge 160xxx only */ if (le16_to_cpu(hdw->usb_dev->descriptor.idVendor) == 0x2040 &&
(le16_to_cpu(hdw->usb_dev->descriptor.idProduct) == 0x7502 ||
le16_to_cpu(hdw->usb_dev->descriptor.idProduct) == 0x7510)) {
pr_debug("%s(): resetting demod on Hauppauge 160xxx platform skipped\n",
__func__); /* Can't reset 160xxx or it will trash Demod tristate */ return pvr2_issue_simple_cmd(hdw,
FX2CMD_HCW_MAKO_SLEEP_PIN |
(1 << 8) |
((onoff ? 1 : 0) << 16));
}
staticvoid pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl)
{ int cmode; /* Compare digital/analog desired setting with current setting. If
they don't match, fix it... */
cmode = (digitalFl ? PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG); if (cmode == hdw->pathway_state) { /* They match; nothing to do */ return;
}
switch (hdw->hdw_desc->digital_control_scheme) { case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
pvr2_hdw_cmd_hcw_demod_reset(hdw,digitalFl); if (cmode == PVR2_PATHWAY_ANALOG) { /* If moving to analog mode, also force the decoder toreset.Ifnodecoderisattached,thenit's oktoignorethisbecauseif/whenthedecoder
attaches, it will reset itself at that time. */
pvr2_hdw_cmd_decoder_reset(hdw);
} break; case PVR2_DIGITAL_SCHEME_ONAIR: /* Supposedly we should always have the power on whether in digitaloranalogmode.Butfornowdowhatappearsto
work... */
pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,digitalFl); break; default: break;
}
/* Stop / start video stream transport */ staticint pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
{ int ret;
/* If we're in analog mode, then just issue the usual analog
command. */ if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) { return pvr2_issue_simple_cmd(hdw,
(runFl ?
FX2CMD_STREAMING_ON :
FX2CMD_STREAMING_OFF)); /*Note: Not reached */
}
if (hdw->pathway_state != PVR2_PATHWAY_DIGITAL) { /* Whoops, we don't know what mode we're in... */ return -EINVAL;
}
/* To get here we have to be in digital mode. The mechanism here isunfortunatelydifferentfordifferentvendors.Soweswitch onthedevice'sdigitalschemeattributeinordertofigureout
what to do. */ switch (hdw->hdw_desc->digital_control_scheme) { case PVR2_DIGITAL_SCHEME_HAUPPAUGE: return pvr2_issue_simple_cmd(hdw,
(runFl ?
FX2CMD_HCW_DTV_STREAMING_ON :
FX2CMD_HCW_DTV_STREAMING_OFF)); case PVR2_DIGITAL_SCHEME_ONAIR:
ret = pvr2_issue_simple_cmd(hdw,
(runFl ?
FX2CMD_STREAMING_ON :
FX2CMD_STREAMING_OFF)); if (ret) return ret; return pvr2_hdw_cmd_onair_digital_path_ctrl(hdw,runFl); default: return -EINVAL;
}
}
/* Evaluate whether or not state_pathway_ok can change */ staticint state_eval_pathway_ok(struct pvr2_hdw *hdw)
{ if (hdw->state_pathway_ok) { /* Nothing to do if pathway is already ok */ return0;
} if (!hdw->state_pipeline_idle) { /* Not allowed to change anything if pipeline is not idle */ return0;
}
pvr2_hdw_cmd_modeswitch(hdw,hdw->input_val == PVR2_CVAL_INPUT_DTV);
hdw->state_pathway_ok = !0;
trace_stbit("state_pathway_ok",hdw->state_pathway_ok); return !0;
}
/* Evaluate whether or not state_encoder_ok can change */ staticint state_eval_encoder_ok(struct pvr2_hdw *hdw)
{ if (hdw->state_encoder_ok) return0; if (hdw->flag_tripped) return0; if (hdw->state_encoder_run) return0; if (hdw->state_encoder_config) return0; if (hdw->state_decoder_run) return0; if (hdw->state_usbstream_run) return0; if (hdw->pathway_state == PVR2_PATHWAY_DIGITAL) { if (!hdw->hdw_desc->flag_digital_requires_cx23416) return0;
} elseif (hdw->pathway_state != PVR2_PATHWAY_ANALOG) { return0;
}
/* Evaluate whether or not state_encoder_config can change */ staticint state_eval_encoder_config(struct pvr2_hdw *hdw)
{ if (hdw->state_encoder_config) { if (hdw->state_encoder_ok) { if (hdw->state_pipeline_req &&
!hdw->state_pipeline_pause) return0;
}
hdw->state_encoder_config = 0;
hdw->state_encoder_waitok = 0;
trace_stbit("state_encoder_waitok",hdw->state_encoder_waitok); /* paranoia - solve race if timer just completed */
timer_delete_sync(&hdw->encoder_wait_timer);
} else { if (!hdw->state_pathway_ok ||
(hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
!hdw->state_encoder_ok ||
!hdw->state_pipeline_idle ||
hdw->state_pipeline_pause ||
!hdw->state_pipeline_req ||
!hdw->state_pipeline_config) { /* We must reset the enforced wait interval if anythinghashappenedthatmighthavedisturbed
the encoder. This should be a rare case. */ if (timer_pending(&hdw->encoder_wait_timer)) {
timer_delete_sync(&hdw->encoder_wait_timer);
} if (hdw->state_encoder_waitok) { /* Must clear the state - therefore we did somethingtoastatebitandmustalso
return true. */
hdw->state_encoder_waitok = 0;
trace_stbit("state_encoder_waitok",
hdw->state_encoder_waitok); return !0;
} return0;
} if (!hdw->state_encoder_waitok) { if (!timer_pending(&hdw->encoder_wait_timer)) { /* waitok flag wasn't set and timer isn't running.Checkflagoncemoretoavoid aracethenstartthetimer.Thisis thepointwhenwemeasureoutaminimal quietintervalbeforedoingsomethingto
the encoder. */ if (!hdw->state_encoder_waitok) {
hdw->encoder_wait_timer.expires =
jiffies + msecs_to_jiffies(
TIME_MSEC_ENCODER_WAIT);
add_timer(&hdw->encoder_wait_timer);
}
} /* We can't continue until we know we have been quietfortheintervalmeasuredbythis
timer. */ return0;
}
pvr2_encoder_configure(hdw); if (hdw->state_encoder_ok) hdw->state_encoder_config = !0;
}
trace_stbit("state_encoder_config",hdw->state_encoder_config); return !0;
}
/* Return true if the encoder should not be running. */ staticint state_check_disable_encoder_run(struct pvr2_hdw *hdw)
{ if (!hdw->state_encoder_ok) { /* Encoder isn't healthy at the moment, so stop it. */ return !0;
} if (!hdw->state_pathway_ok) { /* Mode is not understood at the moment (i.e. it wants to
change), so encoder must be stopped. */ return !0;
}
switch (hdw->pathway_state) { case PVR2_PATHWAY_ANALOG: if (!hdw->state_decoder_run) { /* We're in analog mode and the decoder is not running;thustheencodershouldbestoppedas
well. */ return !0;
} break; case PVR2_PATHWAY_DIGITAL: if (hdw->state_encoder_runok) { /* This is a funny case. We're in digital mode so reallytheencodershouldbestopped.However ifitreallyisrunning,onlykillitafter runokhasbeenset.Thisgivesachanceforthe onairquirktofunction(encodermustrun brieflyfirst,atleastonce,beforeonair
digital streaming can work). */ return !0;
} break; default: /* Unknown mode; so encoder should be stopped. */ return !0;
}
/* If we get here, we haven't found a reason to stop the
encoder. */ return0;
}
/* Return true if the encoder should be running. */ staticint state_check_enable_encoder_run(struct pvr2_hdw *hdw)
{ if (!hdw->state_encoder_ok) { /* Don't run the encoder if it isn't healthy... */ return0;
} if (!hdw->state_pathway_ok) { /* Don't run the encoder if we don't (yet) know what mode
we need to be in... */ return0;
}
switch (hdw->pathway_state) { case PVR2_PATHWAY_ANALOG: if (hdw->state_decoder_run && hdw->state_decoder_ready) { /* In analog mode, if the decoder is running, then
run the encoder. */ return !0;
} break; case PVR2_PATHWAY_DIGITAL: if ((hdw->hdw_desc->digital_control_scheme ==
PVR2_DIGITAL_SCHEME_ONAIR) &&
!hdw->state_encoder_runok) { /* This is a quirk. OnAir hardware won't stream digitaluntiltheencoderhasbeenrunatleast once,foraminimalperiodoftime(empiricially measuredtobe1/4second).Soifwe'reon OnAirhardwareandtheencoderhasneverbeen runatall,thenstarttheencoder.Normal statemachinelogicinthedriverwill
automatically handle the remaining bits. */ return !0;
} break; default: /* For completeness (unknown mode; encoder won't run ever) */ break;
} /* If we get here, then we haven't found any reason to run the
encoder, so don't run it. */ return0;
}
/* Evaluate whether or not state_encoder_run can change */ staticint state_eval_encoder_run(struct pvr2_hdw *hdw)
{ if (hdw->state_encoder_run) { if (!state_check_disable_encoder_run(hdw)) return0; if (hdw->state_encoder_ok) {
timer_delete_sync(&hdw->encoder_run_timer); if (pvr2_encoder_stop(hdw) < 0) return !0;
}
hdw->state_encoder_run = 0;
} else { if (!state_check_enable_encoder_run(hdw)) return0; if (pvr2_encoder_start(hdw) < 0) return !0;
hdw->state_encoder_run = !0; if (!hdw->state_encoder_runok) {
hdw->encoder_run_timer.expires = jiffies +
msecs_to_jiffies(TIME_MSEC_ENCODER_OK);
add_timer(&hdw->encoder_run_timer);
}
}
trace_stbit("state_encoder_run",hdw->state_encoder_run); return !0;
}
/* Timeout function for encoder run timer. */ staticvoid pvr2_hdw_encoder_run_timeout(struct timer_list *t)
{ struct pvr2_hdw *hdw = timer_container_of(hdw, t, encoder_run_timer); if (!hdw->state_encoder_runok) {
hdw->state_encoder_runok = !0;
trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
hdw->state_stale = !0;
schedule_work(&hdw->workpoll);
}
}
/* Evaluate whether or not state_decoder_run can change */ staticint state_eval_decoder_run(struct pvr2_hdw *hdw)
{ if (hdw->state_decoder_run) { if (hdw->state_encoder_ok) { if (hdw->state_pipeline_req &&
!hdw->state_pipeline_pause &&
hdw->state_pathway_ok) return0;
} if (!hdw->flag_decoder_missed) {
pvr2_decoder_enable(hdw,0);
}
hdw->state_decoder_quiescent = 0;
hdw->state_decoder_run = 0; /* paranoia - solve race if timer(s) just completed */
timer_delete_sync(&hdw->quiescent_timer); /* Kill the stabilization timer, in case we're killing the encoderbeforethepreviousstabilizationintervalhas
been properly timed. */
timer_delete_sync(&hdw->decoder_stabilization_timer);
hdw->state_decoder_ready = 0;
} else { if (!hdw->state_decoder_quiescent) { if (!timer_pending(&hdw->quiescent_timer)) { /* We don't do something about the quiescenttimeruntilrightherebecause wealsowanttocatchcaseswherethe decoderwasalreadynotrunning(like afterinitialization)asopposedto knowingthatwehadjuststoppedit. Thesecondflagcheckisheretocovera race-thetimercouldhaverunandset thisflagjustafterthepreviouscheck
but before we did the pending check. */ if (!hdw->state_decoder_quiescent) {
hdw->quiescent_timer.expires =
jiffies + msecs_to_jiffies(
TIME_MSEC_DECODER_WAIT);
add_timer(&hdw->quiescent_timer);
}
} /* Don't allow decoder to start again until it has beenquiescedfirst.Thislittledetailshould
hopefully further stabilize the encoder. */ return0;
} if (!hdw->state_pathway_ok ||
(hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
!hdw->state_pipeline_req ||
hdw->state_pipeline_pause ||
!hdw->state_pipeline_config ||
!hdw->state_encoder_config ||
!hdw->state_encoder_ok) return0;
timer_delete_sync(&hdw->quiescent_timer); if (hdw->flag_decoder_missed) return0; if (pvr2_decoder_enable(hdw,!0) < 0) return0;
hdw->state_decoder_quiescent = 0;
hdw->state_decoder_ready = 0;
hdw->state_decoder_run = !0; if (hdw->decoder_client_id == PVR2_CLIENT_ID_SAA7115) {
hdw->decoder_stabilization_timer.expires =
jiffies + msecs_to_jiffies(
TIME_MSEC_DECODER_STABILIZATION_WAIT);
add_timer(&hdw->decoder_stabilization_timer);
} else {
hdw->state_decoder_ready = !0;
}
}
trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent);
trace_stbit("state_decoder_run",hdw->state_decoder_run);
trace_stbit("state_decoder_ready", hdw->state_decoder_ready); return !0;
}
/* Evaluate whether or not state_usbstream_run can change */ staticint state_eval_usbstream_run(struct pvr2_hdw *hdw)
{ if (hdw->state_usbstream_run) { int fl = !0; if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
fl = (hdw->state_encoder_ok &&
hdw->state_encoder_run);
} elseif ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
(hdw->hdw_desc->flag_digital_requires_cx23416)) {
fl = hdw->state_encoder_ok;
} if (fl &&
hdw->state_pipeline_req &&
!hdw->state_pipeline_pause &&
hdw->state_pathway_ok) { return0;
}
pvr2_hdw_cmd_usbstream(hdw,0);
hdw->state_usbstream_run = 0;
} else { if (!hdw->state_pipeline_req ||
hdw->state_pipeline_pause ||
!hdw->state_pathway_ok) return0; if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) { if (!hdw->state_encoder_ok ||
!hdw->state_encoder_run) return0;
} elseif ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
(hdw->hdw_desc->flag_digital_requires_cx23416)) { if (!hdw->state_encoder_ok) return0; if (hdw->state_encoder_run) return0; if (hdw->hdw_desc->digital_control_scheme ==
PVR2_DIGITAL_SCHEME_ONAIR) { /* OnAir digital receivers won't stream unlesstheanalogencoderhasrunfirst. Why?Ihavenoidea.Butdon'teven tryuntilweknowtheanalogsideis
known to have run. */ if (!hdw->state_encoder_runok) return0;
}
} if (pvr2_hdw_cmd_usbstream(hdw,!0) < 0) return0;
hdw->state_usbstream_run = !0;
}
trace_stbit("state_usbstream_run",hdw->state_usbstream_run); return !0;
}
/* Attempt to configure pipeline, if needed */ staticint state_eval_pipeline_config(struct pvr2_hdw *hdw)
{ if (hdw->state_pipeline_config ||
hdw->state_pipeline_pause) return0;
pvr2_hdw_commit_execute(hdw); return !0;
}
/* Update pipeline idle and pipeline pause tracking states based on other inputs.Thismustbecalledwhenevertheotherrelevantinputshave
changed. */ staticint state_update_pipeline_state(struct pvr2_hdw *hdw)
{ unsignedint st; int updatedFl = 0; /* Update pipeline state */
st = !(hdw->state_encoder_run ||
hdw->state_decoder_run ||
hdw->state_usbstream_run ||
(!hdw->state_decoder_quiescent)); if (!st != !hdw->state_pipeline_idle) {
hdw->state_pipeline_idle = st;
updatedFl = !0;
} if (hdw->state_pipeline_idle && hdw->state_pipeline_pause) {
hdw->state_pipeline_pause = 0;
updatedFl = !0;
} return updatedFl;
}
typedefint (*state_eval_func)(struct pvr2_hdw *);
/* Set of functions to be run to evaluate various states in the driver. */ staticconst state_eval_func eval_funcs[] = {
state_eval_pathway_ok,
state_eval_pipeline_config,
state_eval_encoder_ok,
state_eval_encoder_config,
state_eval_decoder_run,
state_eval_encoder_run,
state_eval_usbstream_run,
};
/* Process various states and return true if we did anything interesting. */ staticint pvr2_hdw_state_update(struct pvr2_hdw *hdw)
{ unsignedint i; int state_updated = 0; int check_flag;
if (!hdw->state_stale) return0; if ((hdw->fw1_state != FW1_STATE_OK) ||
!hdw->flag_ok) {
hdw->state_stale = 0; return !0;
} /* This loop is the heart of the entire driver. It keeps trying to evaluatevariousbitsofdriverstateuntilnothingchangesfor onefulliteration.Each"bitofstate"trackssomeglobal aspectofthedriver,e.g.whetherdecodershouldrun,if pipelineisconfigured,usbstreamingison,etc.Weseparately evaluateeachofthosequestionsbasedonotherdriverstateto
arrive at the correct running configuration. */ do {
check_flag = 0;
state_update_pipeline_state(hdw); /* Iterate over each bit of state */ for (i = 0; (i<ARRAY_SIZE(eval_funcs)) && hdw->flag_ok; i++) { if ((*eval_funcs[i])(hdw)) {
check_flag = !0;
state_updated = !0;
state_update_pipeline_state(hdw);
}
}
} while (check_flag && hdw->flag_ok);
hdw->state_stale = 0;
trace_stbit("state_stale",hdw->state_stale); return state_updated;
}
/* Evaluate and update the driver's current state, taking various actions
as appropriate for the update. */ staticint pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
{ unsignedint st; int state_updated = 0; int callback_flag = 0; int analog_mode;
pvr2_trace(PVR2_TRACE_STBITS, "Drive state check START"); if (pvrusb2_debug & PVR2_TRACE_STBITS) {
pvr2_hdw_state_log_state(hdw);
}
/* Process all state and get back over disposition */
state_updated = pvr2_hdw_state_update(hdw);
/* Handle side effects - if we switch to a mode that needs the RF tuner,thenselecttherightfrequencychoiceaswellandmark
it dirty. */ if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
hdw->freqSelector = 0;
hdw->freqDirty = !0;
} elseif ((hdw->input_val == PVR2_CVAL_INPUT_TV) ||
(hdw->input_val == PVR2_CVAL_INPUT_DTV)) {
hdw->freqSelector = 1;
hdw->freqDirty = !0;
} return0;
}
int pvr2_hdw_set_input_allowed(struct pvr2_hdw *hdw, unsignedint change_mask, unsignedint change_val)
{ int ret = 0; unsignedint nv,m,idx;
LOCK_TAKE(hdw->big_lock); do {
nv = hdw->input_allowed_mask & ~change_mask;
nv |= (change_val & change_mask);
nv &= hdw->input_avail_mask; if (!nv) { /* No legal modes left; return error instead. */
ret = -EPERM; break;
}
hdw->input_allowed_mask = nv; if ((1UL << hdw->input_val) & hdw->input_allowed_mask) { /* Current mode is still in the allowed mask, so
we're done. */ break;
} /* Select and switch to a mode that is still in the allowed
mask */ if (!hdw->input_allowed_mask) { /* Nothing legal; give up */ break;
}
m = hdw->input_allowed_mask; for (idx = 0; idx < (sizeof(m) << 3); idx++) { if (!((1UL << idx) & m)) continue;
pvr2_hdw_set_input(hdw,idx); break;
}
} while (0);
LOCK_GIVE(hdw->big_lock); return ret;
}
/* Find I2C address of eeprom */ staticint pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
{ int result;
LOCK_TAKE(hdw->ctl_lock); do {
hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR;
result = pvr2_send_request(hdw,
hdw->cmd_buffer,1,
hdw->cmd_buffer,1); if (result < 0) break;
result = hdw->cmd_buffer[0];
} while(0); LOCK_GIVE(hdw->ctl_lock); return result;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.118 Sekunden
(vorverarbeitet am 2026-10-02)
¤