From 47e43210de3ddc110b1b784c26cc1d78f6e5127d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 24 Aug 2009 22:39:50 +0000 Subject: [PATCH] Reenable dvb-usb-af9005 using request_firmware(); note that this addresses bug #494119 svn path=/dists/trunk/linux-2.6/; revision=14186 --- debian/changelog | 4 +- ...edia-dvb-usb-af9005-request_firmware.patch | 152 ++++++++++++++++++ debian/patches/series/base | 1 + 3 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch diff --git a/debian/changelog b/debian/changelog index 9a1a6c7dd..a0bf4a6c4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -58,7 +58,9 @@ linux-2.6 (2.6.31~rc7-1~experimental.1) UNRELEASED; urgency=low thanks to Kalle Olavi Niemitalo * ib_ipath: remove firmware for QLogic IBA7220 and use request_firmware() to load it - * dvb-usb-af9005: remove firmware and disable + * dvb-usb-af9005: remove initialisation script derived from Windows + driver and use request_firmware() to extract it at run-time + (closes: #494119) * Add warning on upgrade to a new upstream version where the system appears to be missing necessary firmware files (closes: #541702) * qla1280: Release spinlock when requesting firmware (closes: #543244) diff --git a/debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch b/debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch new file mode 100644 index 000000000..91c4a1f52 --- /dev/null +++ b/debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch @@ -0,0 +1,152 @@ +From 0b8d838ecaa0235000347c084d192aa30b76ae70 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Mon, 24 Aug 2009 23:19:58 +0100 +Subject: [PATCH] af9005: Use request_firmware() to load register init script + +Read the register init script from the Windows driver. This is sick +but should avoid the potential copyright infringement in distributing +a version of the script which is directly derived from the driver. +--- + drivers/media/dvb/dvb-usb/Kconfig | 2 +- + drivers/media/dvb/dvb-usb/af9005-fe.c | 66 ++++++++++++++++++++++++++------ + 2 files changed, 54 insertions(+), 14 deletions(-) + +diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig +index 868e1cb..1c3d56d 100644 +--- a/drivers/media/dvb/dvb-usb/Kconfig ++++ b/drivers/media/dvb/dvb-usb/Kconfig +@@ -238,10 +238,10 @@ config DVB_USB_OPERA1 + + config DVB_USB_AF9005 + tristate "Afatech AF9005 DVB-T USB1.1 support" +- depends on BROKEN + depends on DVB_USB && EXPERIMENTAL + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE ++ select FW_LOADER + help + Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver + and the TerraTec Cinergy T USB XE (Rev.1) +diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c +index 199ece0..bcc26c8 100644 +--- a/drivers/media/dvb/dvb-usb/af9005-fe.c ++++ b/drivers/media/dvb/dvb-usb/af9005-fe.c +@@ -22,10 +22,26 @@ + * see Documentation/dvb/README.dvb-usb for more information + */ + #include "af9005.h" +-#include "af9005-script.h" + #include "mt2060.h" + #include "qt1010.h" + #include ++#include ++ ++/* Register initialisation script to be extracted from the Windows driver */ ++ ++typedef struct { ++ __le16 reg; ++ u8 pos; ++ u8 len; ++ u8 val; ++ u8 pad; ++} __packed RegDesc; ++ ++#define WIN_DRV_NAME "AF05BDA.sys" ++#define WIN_DRV_VERSION "6.3.2.1" ++#define WIN_DRV_SIZE 133504 ++#define WIN_DRV_SCRIPT_OFFSET 88316 ++#define WIN_DRV_SCRIPT_SIZE 1110 + + struct af9005_fe_state { + struct dvb_usb_device *d; +@@ -818,6 +834,8 @@ static int af9005_fe_init(struct dvb_frontend *fe) + { + struct af9005_fe_state *state = fe->demodulator_priv; + struct dvb_usb_adapter *adap = fe->dvb->priv; ++ const struct firmware *fw; ++ const RegDesc *script; + int ret, i, scriptlen; + u8 temp, temp0 = 0, temp1 = 0, temp2 = 0; + u8 buf[2]; +@@ -969,37 +987,55 @@ static int af9005_fe_init(struct dvb_frontend *fe) + if ((ret = af9005_write_ofdm_register(state->d, 0xaefb, 0x01))) + return ret; + +- /* load init script */ +- deb_info("load init script\n"); +- scriptlen = sizeof(script) / sizeof(RegDesc); ++ /* load and validate init script */ ++ deb_info("load init script from Windows driver\n"); ++ ret = request_firmware(&fw, WIN_DRV_NAME, &state->d->udev->dev); ++ if (ret) ++ return ret; ++ BUILD_BUG_ON(sizeof(RegDesc) != 6); ++ if (fw->size != WIN_DRV_SIZE || ++ memcmp(fw->data + WIN_DRV_SCRIPT_OFFSET, ++ "\x80\xa1\x00\x08\x0a\x00", 6) || ++ memcmp(fw->data + WIN_DRV_SCRIPT_OFFSET + WIN_DRV_SCRIPT_SIZE - 6, ++ "\x49\xa3\x00\x06\x02\x00", 6)) { ++ err("%s is invalid - should be version %s, size %u bytes\n", ++ WIN_DRV_NAME, WIN_DRV_VERSION, WIN_DRV_SIZE); ++ ret = -EINVAL; ++ goto fail_release; ++ } ++ ++ script = (const RegDesc *)(fw->data + WIN_DRV_SCRIPT_OFFSET); ++ scriptlen = WIN_DRV_SCRIPT_SIZE / sizeof(RegDesc); + for (i = 0; i < scriptlen; i++) { ++ u16 reg = le16_to_cpu(script[i].reg); + if ((ret = +- af9005_write_register_bits(state->d, script[i].reg, ++ af9005_write_register_bits(state->d, reg, + script[i].pos, + script[i].len, script[i].val))) +- return ret; ++ goto fail_release; + /* save 3 bytes of original fcw */ +- if (script[i].reg == 0xae18) ++ if (reg == 0xae18) + temp2 = script[i].val; +- if (script[i].reg == 0xae19) ++ if (reg == 0xae19) + temp1 = script[i].val; +- if (script[i].reg == 0xae1a) ++ if (reg == 0xae1a) + temp0 = script[i].val; + + /* save original unplug threshold */ +- if (script[i].reg == xd_p_reg_unplug_th) ++ if (reg == xd_p_reg_unplug_th) + state->original_if_unplug_th = script[i].val; +- if (script[i].reg == xd_p_reg_unplug_rf_gain_th) ++ if (reg == xd_p_reg_unplug_rf_gain_th) + state->original_rf_unplug_th = script[i].val; +- if (script[i].reg == xd_p_reg_unplug_dtop_if_gain_th) ++ if (reg == xd_p_reg_unplug_dtop_if_gain_th) + state->original_dtop_if_unplug_th = script[i].val; +- if (script[i].reg == xd_p_reg_unplug_dtop_rf_gain_th) ++ if (reg == xd_p_reg_unplug_dtop_rf_gain_th) + state->original_dtop_rf_unplug_th = script[i].val; + + } + state->original_fcw = + ((u32) temp2 << 16) + ((u32) temp1 << 8) + (u32) temp0; + ++ release_firmware(fw); + + /* save original TOPs */ + deb_info("save original TOPs\n"); +@@ -1079,6 +1115,10 @@ static int af9005_fe_init(struct dvb_frontend *fe) + + deb_info("profit!\n"); + return 0; ++ ++fail_release: ++ release_firmware(fw); ++ return ret; + } + + static int af9005_fe_sleep(struct dvb_frontend *fe) +-- +1.6.3.3 + diff --git a/debian/patches/series/base b/debian/patches/series/base index 6aa121636..df36b1a64 100644 --- a/debian/patches/series/base +++ b/debian/patches/series/base @@ -10,6 +10,7 @@ + features/all/drivers-gpu-drm-r128-request_firmware.patch + features/all/drivers-gpu-drm-radeon-request_firmware.patch + features/all/drivers-infiniband-hw-ipath-iba7220-use-request_firmware.patch ++ features/all/drivers-media-dvb-usb-af9005-request_firmware.patch + features/all/drivers-net-cxgb3-request_firmware.patch + features/all/drivers-staging-rt28x0sta-request_firmware.patch + features/all/export-unionfs-symbols.patch