diff options
-rw-r--r-- | drivers/media/dvb/dvb-usb/Kconfig | 4 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dvb_usb_firmware.c | 125 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dvb_usb_firmware.h | 31 |
4 files changed, 162 insertions, 0 deletions
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 2f6973a24cc6..3e75fcdb33cc 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -28,6 +28,10 @@ config DVB_USB_V2 | |||
28 | 28 | ||
29 | Say Y if you own a USB DVB device. | 29 | Say Y if you own a USB DVB device. |
30 | 30 | ||
31 | config DVB_USB_FIRMWARE | ||
32 | tristate "Firmware helper routines" | ||
33 | depends on DVB_USB | ||
34 | |||
31 | config DVB_USB_DEBUG | 35 | config DVB_USB_DEBUG |
32 | bool "Enable extended debug support for all DVB-USB devices" | 36 | bool "Enable extended debug support for all DVB-USB devices" |
33 | depends on DVB_USB | 37 | depends on DVB_USB |
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 3c73e7b2a9f8..a0f5be28ca72 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
@@ -4,6 +4,8 @@ obj-$(CONFIG_DVB_USB) += dvb-usb.o | |||
4 | dvb_usbv2-objs = dvb_usb_init.o dvb_usb_urb.o dvb_usb_dvb.o dvb_usb_remote.o usb_urb.o | 4 | dvb_usbv2-objs = dvb_usb_init.o dvb_usb_urb.o dvb_usb_dvb.o dvb_usb_remote.o usb_urb.o |
5 | obj-$(CONFIG_DVB_USB_V2) += dvb_usbv2.o | 5 | obj-$(CONFIG_DVB_USB_V2) += dvb_usbv2.o |
6 | 6 | ||
7 | obj-$(CONFIG_DVB_USB_FIRMWARE) += dvb_usb_firmware.o | ||
8 | |||
7 | dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o | 9 | dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o |
8 | obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o | 10 | obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o |
9 | 11 | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb_usb_firmware.c b/drivers/media/dvb/dvb-usb/dvb_usb_firmware.c new file mode 100644 index 000000000000..61c3fe9a599e --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb_usb_firmware.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* dvb_usb_firmware.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for downloading the firmware to Cypress FX 1 | ||
7 | * and 2 based devices. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include "dvb_usb.h" | ||
12 | #include "dvb_usb_firmware.h" | ||
13 | |||
14 | struct usb_cypress_controller { | ||
15 | u8 id; | ||
16 | const char *name; /* name of the usb controller */ | ||
17 | u16 cs_reg; /* needs to be restarted, | ||
18 | * when the firmware has been downloaded */ | ||
19 | }; | ||
20 | |||
21 | static const struct usb_cypress_controller cypress[] = { | ||
22 | { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cs_reg = 0x7f92 }, | ||
23 | { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cs_reg = 0x7f92 }, | ||
24 | { .id = CYPRESS_FX2, .name = "Cypress FX2", .cs_reg = 0xe600 }, | ||
25 | }; | ||
26 | |||
27 | /* | ||
28 | * load a firmware packet to the device | ||
29 | */ | ||
30 | static int usb_cypress_writemem(struct usb_device *udev, u16 addr, u8 *data, | ||
31 | u8 len) | ||
32 | { | ||
33 | return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
34 | 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000); | ||
35 | } | ||
36 | |||
37 | int usbv2_cypress_load_firmware(struct usb_device *udev, | ||
38 | const struct firmware *fw, int type) | ||
39 | { | ||
40 | struct hexline hx; | ||
41 | u8 reset; | ||
42 | int ret, pos = 0; | ||
43 | |||
44 | /* stop the CPU */ | ||
45 | reset = 1; | ||
46 | ret = usb_cypress_writemem(udev, cypress[type].cs_reg, &reset, 1); | ||
47 | if (ret != 1) | ||
48 | pr_err("%s: could not stop the USB controller CPU", | ||
49 | KBUILD_MODNAME); | ||
50 | |||
51 | while ((ret = dvb_usbv2_get_hexline(fw, &hx, &pos)) > 0) { | ||
52 | pr_debug("%s: writing to address %04x (buffer: %02x %02x)\n", | ||
53 | __func__, hx.addr, hx.len, hx.chk); | ||
54 | |||
55 | ret = usb_cypress_writemem(udev, hx.addr, hx.data, hx.len); | ||
56 | if (ret != hx.len) { | ||
57 | pr_err("%s: error while transferring firmware " \ | ||
58 | "(transferred size=%d, block size=%d)", | ||
59 | KBUILD_MODNAME, ret, hx.len); | ||
60 | ret = -EINVAL; | ||
61 | break; | ||
62 | } | ||
63 | } | ||
64 | if (ret < 0) { | ||
65 | pr_err("%s: firmware download failed at %d with %d", | ||
66 | KBUILD_MODNAME, pos, ret); | ||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | if (ret == 0) { | ||
71 | /* restart the CPU */ | ||
72 | reset = 0; | ||
73 | if (ret || usb_cypress_writemem( | ||
74 | udev, cypress[type].cs_reg, &reset, 1) != 1) { | ||
75 | pr_err("%s: could not restart the USB controller CPU", | ||
76 | KBUILD_MODNAME); | ||
77 | ret = -EINVAL; | ||
78 | } | ||
79 | } else | ||
80 | ret = -EIO; | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | EXPORT_SYMBOL(usbv2_cypress_load_firmware); | ||
85 | |||
86 | int dvb_usbv2_get_hexline(const struct firmware *fw, struct hexline *hx, | ||
87 | int *pos) | ||
88 | { | ||
89 | u8 *b = (u8 *) &fw->data[*pos]; | ||
90 | int data_offs = 4; | ||
91 | |||
92 | if (*pos >= fw->size) | ||
93 | return 0; | ||
94 | |||
95 | memset(hx, 0, sizeof(struct hexline)); | ||
96 | |||
97 | hx->len = b[0]; | ||
98 | |||
99 | if ((*pos + hx->len + 4) >= fw->size) | ||
100 | return -EINVAL; | ||
101 | |||
102 | hx->addr = b[1] | (b[2] << 8); | ||
103 | hx->type = b[3]; | ||
104 | |||
105 | if (hx->type == 0x04) { | ||
106 | /* b[4] and b[5] are the Extended linear address record data | ||
107 | * field */ | ||
108 | hx->addr |= (b[4] << 24) | (b[5] << 16); | ||
109 | /* | ||
110 | hx->len -= 2; | ||
111 | data_offs += 2; | ||
112 | */ | ||
113 | } | ||
114 | memcpy(hx->data, &b[data_offs], hx->len); | ||
115 | hx->chk = b[hx->len + data_offs]; | ||
116 | |||
117 | *pos += hx->len + 5; | ||
118 | |||
119 | return *pos; | ||
120 | } | ||
121 | EXPORT_SYMBOL(dvb_usbv2_get_hexline); | ||
122 | |||
123 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
124 | MODULE_DESCRIPTION("Cypress firmware download"); | ||
125 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb_usb_firmware.h b/drivers/media/dvb/dvb-usb/dvb_usb_firmware.h new file mode 100644 index 000000000000..358d9d0b1899 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb_usb_firmware.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* dvb_usb_firmware.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for downloading the firmware to Cypress FX 1 | ||
7 | * and 2 based devices. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #ifndef DVB_USB_FIRMWARE_H | ||
12 | #define DVB_USB_FIRMWARE_H | ||
13 | |||
14 | #define CYPRESS_AN2135 0 | ||
15 | #define CYPRESS_AN2235 1 | ||
16 | #define CYPRESS_FX2 2 | ||
17 | |||
18 | /* commonly used firmware download types and function */ | ||
19 | struct hexline { | ||
20 | u8 len; | ||
21 | u32 addr; | ||
22 | u8 type; | ||
23 | u8 data[255]; | ||
24 | u8 chk; | ||
25 | }; | ||
26 | extern int usbv2_cypress_load_firmware(struct usb_device *, | ||
27 | const struct firmware *, int); | ||
28 | extern int dvb_usbv2_get_hexline(const struct firmware *, | ||
29 | struct hexline *, int *); | ||
30 | |||
31 | #endif | ||