staticint no_poweroff;
module_param(no_poweroff, int, 0644);
MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n" "1 keep device energized and with tuner ready all the times.\n" " Faster, but consumes more power and keeps the device hotter\n");
staticchar audio_std[8];
module_param_string(audio_std, audio_std, sizeof(audio_std), 0);
MODULE_PARM_DESC(audio_std, "Audio standard. XC3028 audio decoder explicitly needs to know what audio\n" "standard is needed for some video standards with audio A2 or NICAM.\n" "The valid values are:\n" "A2\n" "A2/A\n" "A2/B\n" "NICAM\n" "NICAM/A\n" "NICAM/B\n");
/* Seek for exact match */ for (i = 0; i < priv->firm_size; i++) { if ((type == (priv->firm[i].type & type_mask)) &&
(*id == priv->firm[i].id)) goto found;
}
/* Seek for generic video standard match */ for (i = 0; i < priv->firm_size; i++) {
v4l2_std_id match_mask; int nr_matches;
if (type != (priv->firm[i].type & type_mask)) continue;
match_mask = *id & priv->firm[i].id; if (!match_mask) continue;
if ((*id & match_mask) == *id) goto found; /* Supports all the requested standards */
if (best_nr_matches > 0) {
tuner_dbg("Selecting best matching firmware (%d bits) for type=",
best_nr_matches);
dump_firm_type(type);
printk(KERN_CONT "(%x), id %016llx:\n", type, (unsignedlonglong)*id);
i = best_i; goto found;
}
/*FIXME: Would make sense to seek for type "hint" match ? */
i = -ENOENT; goto ret;
found:
*id = priv->firm[i].id;
ret:
tuner_dbg("%s firmware for type=", (i < 0) ? "Can't find" : "Found"); if (debug) {
dump_firm_type(type);
printk(KERN_CONT "(%x), id %016llx.\n",
type, (unsignedlonglong)*id);
} return i;
}
staticinlineint do_tuner_callback(struct dvb_frontend *fe, int cmd, int arg)
{ struct xc2028_data *priv = fe->tuner_priv;
/* analog side (tuner-core) uses i2c_adap->algo_data. * digital side is not guaranteed to have algo_data defined. * * digital side will always have fe->dvb defined. * analog side (tuner-core) doesn't (yet) define fe->dvb.
*/
tuner_dbg("checking firmware, user requested type="); if (debug) {
dump_firm_type(new_fw.type);
printk(KERN_CONT "(%x), id %016llx, ", new_fw.type,
(unsignedlonglong)new_fw.std_req); if (!int_freq) {
printk(KERN_CONT "scode_tbl ");
dump_firm_type(priv->ctrl.scode_table);
printk(KERN_CONT "(%x), ", priv->ctrl.scode_table);
} else
printk(KERN_CONT "int_freq %d, ", new_fw.int_freq);
printk(KERN_CONT "scode_nr %d\n", new_fw.scode_nr);
}
/* * No need to reload base firmware if it matches and if the tuner * is not at sleep mode
*/ if ((priv->state == XC2028_ACTIVE) &&
(((BASE | new_fw.type) & BASE_TYPES) ==
(priv->cur_fw.type & BASE_TYPES))) {
tuner_dbg("BASE firmware not changed.\n"); goto skip_base;
}
/* Updating BASE - forget about all currently loaded firmware */
memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
/* Reset is needed before loading firmware */
rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0); if (rc < 0) goto fail;
/* BASE firmwares are all std0 */
std0 = 0;
rc = load_firmware(fe, BASE | new_fw.type, &std0); if (rc < 0) {
tuner_err("Error %d while loading base firmware\n",
rc); goto fail;
}
/* Load INIT1, if needed */
tuner_dbg("Load init1 firmware, if exists\n");
skip_base: /* * No need to reload standard specific firmware if base firmware * was not reloaded and requested video standards have not changed.
*/ if (priv->cur_fw.type == (BASE | new_fw.type) &&
priv->cur_fw.std_req == std) {
tuner_dbg("Std-specific firmware already loaded.\n"); goto skip_std_specific;
}
tuner_dbg("Device is Xceive %d version %d.%d, firmware version %d.%d\n",
hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
(version & 0xf0) >> 4, version & 0xf);
if (priv->ctrl.read_not_reliable) goto read_not_reliable;
/* Check firmware version against what we downloaded. */ if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) { if (!priv->ctrl.read_not_reliable) {
tuner_err("Incorrect readback of firmware version.\n"); goto fail;
} else {
tuner_err("Returned an incorrect version. However, read is not reliable enough. Ignoring it.\n");
hwmodel = 3028;
}
}
/* Check that the tuner hardware model remains consistent over time. */ if (priv->hwmodel == 0 && (hwmodel == 2028 || hwmodel == 3028)) {
priv->hwmodel = hwmodel;
priv->hwvers = version & 0xff00;
} elseif (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
priv->hwvers != (version & 0xff00)) {
tuner_err("Read invalid device hardware information - tuner hung?\n"); goto fail;
}
read_not_reliable:
priv->cur_fw = new_fw;
/* * By setting BASE in cur_fw.type only after successfully loading all * firmwares, we can: * 1. Identify that BASE firmware with type=0 has been loaded; * 2. Tell whether BASE firmware was just changed the next time through.
*/
priv->cur_fw.type |= BASE;
priv->state = XC2028_ACTIVE;
tuner_dbg("should set frequency %d kHz\n", freq / 1000);
if (check_firmware(fe, type, std, int_freq) < 0) goto ret;
/* On some cases xc2028 can disable video output, if * very weak signals are received. By sending a soft * reset, this is re-enabled. So, it is better to always * send a soft reset before changing channels, to be sure * that xc2028 will be in a safe state. * Maybe this might also be needed for DTV.
*/ switch (new_type) { case V4L2_TUNER_ANALOG_TV:
rc = send_seq(priv, {0x00, 0x00});
/* Analog mode requires offset = 0 */ break; case V4L2_TUNER_RADIO: /* Radio mode requires offset = 0 */ break; case V4L2_TUNER_DIGITAL_TV: /* * Digital modes require an offset to adjust to the * proper frequency. The offset depends on what * firmware version is used.
*/
/* * Adjust to the center frequency. This is calculated by the * formula: offset = 1.25MHz - BW/2 * For DTV 7/8, the firmware uses BW = 8000, so it needs a * further adjustment to get the frequency center on VHF
*/
/* * The firmware DTV78 used to work fine in UHF band (8 MHz * bandwidth) but not at all in VHF band (7 MHz bandwidth). * The real problem was connected to the formula used to * calculate the center frequency offset in VHF band. * In fact, removing the 500KHz adjustment fixed the problem. * This is coherent to what was implemented for the DTV7 * firmware. * In the end, now the center frequency is the same for all 3 * firmwares (DTV7, DTV8, DTV78) and doesn't depend on channel * bandwidth.
*/
if (priv->cur_fw.type & DTV6)
offset = 1750000; else/* DTV7 or DTV8 or DTV78 */
offset = 2750000;
/* * xc3028 additional "magic" * Depending on the firmware version, it needs some adjustments * to properly centralize the frequency. This seems to be * needed to compensate the SCODE table adjustments made by * newer firmwares
*/
/* * The proper adjustment would be to do it at s-code table. * However, this didn't work, as reported by * Robert Lowery <rglowery@exemail.com.au>
*/
#if 0 /* * Still need tests for XC3028L (firmware 3.2 or upper) * So, for now, let's just comment the per-firmware * version of this change. Reports with xc3028l working * with and without the lines below are welcome
*/
if (priv->firm_version < 0x0302) { if (priv->cur_fw.type & DTV7)
offset += 500000;
} else { if (priv->cur_fw.type & DTV7)
offset -= 300000; elseif (type != ATSC) /* DVB @6MHz, DTV 8 and DTV 7/8 */
offset += 200000;
} #endif break; default:
tuner_err("Unsupported tuner type %d.\n", new_type); break;
}
div = (freq - offset + DIV / 2) / DIV;
/* CMD= Set frequency */ if (priv->firm_version < 0x0202)
rc = send_seq(priv, {0x00, XREG_RF_FREQ, 0x00, 0x00}); else
rc = send_seq(priv, {0x80, XREG_RF_FREQ, 0x00, 0x00}); if (rc < 0) goto ret;
/* Return code shouldn't be checked. The reset CLK is needed only with tm6000. Driver should work fine even if this fails.
*/ if (priv->ctrl.msleep)
msleep(priv->ctrl.msleep);
do_tuner_callback(fe, XC2028_RESET_CLK, 1);
rc = check_device_status(priv); if (rc < 0) return rc;
switch (delsys) { case SYS_DVBT: case SYS_DVBT2: /* * The only countries with 6MHz seem to be Taiwan/Uruguay. * Both seem to require QAM firmware for OFDM decoding * Tested in Taiwan by Terry Wu <terrywu2009@gmail.com>
*/ if (bw <= 6000000)
type |= QAM;
switch (priv->ctrl.type) { case XC2028_D2633:
type |= D2633; break; case XC2028_D2620:
type |= D2620; break; case XC2028_AUTO: default: /* Zarlink seems to need D2633 */ if (priv->ctrl.demod == XC3028_FE_ZARLINK456)
type |= D2633; else
type |= D2620;
} break; case SYS_ATSC: /* The only ATSC firmware (at least on v2.7) is D2633 */
type |= ATSC | D2633; break; /* DVB-S and pure QAM (FE_QAM) are not supported */ default: return -EINVAL;
}
if (bw <= 6000000) {
type |= DTV6;
priv->ctrl.vhfbw7 = 0;
priv->ctrl.uhfbw8 = 0;
} elseif (bw <= 7000000) { if (c->frequency < 470000000)
priv->ctrl.vhfbw7 = 1; else
priv->ctrl.uhfbw8 = 0;
type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7;
type |= F8MHZ;
} else { if (c->frequency < 470000000)
priv->ctrl.vhfbw7 = 0; else
priv->ctrl.uhfbw8 = 1;
type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8;
type |= F8MHZ;
}
/* All S-code tables need a 200kHz shift */ if (priv->ctrl.demod) {
demod = priv->ctrl.demod;
/* * Newer firmwares require a 200 kHz offset only for ATSC
*/ if (type == ATSC || priv->firm_version < 0x0302)
demod += 200; /* * The DTV7 S-code table needs a 700 kHz shift. * * DTV7 is only used in Australia. Germany or Italy may also * use this firmware after initialization, but a tune to a UHF * channel should then cause DTV78 to be used. * * Unfortunately, on real-field tests, the s-code offset * didn't work as expected, as reported by * Robert Lowery <rglowery@exemail.com.au>
*/
}
/* * Copy the config data.
*/
memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
/* * If firmware name changed, frees firmware. As free_firmware will * reset the status to NO_FIRMWARE, this forces a new request_firmware
*/ if (!firmware_name[0] && p->fname &&
priv->fname && strcmp(p->fname, priv->fname))
free_firmware(priv);
if (priv->ctrl.max_len < 9)
priv->ctrl.max_len = 13;
if (priv->state == XC2028_NO_FIRMWARE) { if (!firmware_name[0])
priv->fname = kstrdup(p->fname, GFP_KERNEL); else
priv->fname = firmware_name;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.