diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2013-03-25 05:43:12 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-29 10:35:06 -0400 |
commit | 79a63c60a6a2ae589e44529401e0ab1150e9408a (patch) | |
tree | 8d374af399007ac12e5b64d6b45f2da99435ed91 /drivers/media/common | |
parent | 38a46c2128ade2a0c6ee4438297180b09a01c309 (diff) |
[media] media: move dvb-usb-v2/cypress_firmware.c to media/common
Loading the cypress firmware is not dvb specific and should be common
functionality. Move the source to media/common and make it a standalone
module.
As a result we can remove the dependency on dvb-usb in go7007, which has
nothing to do with dvb.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/common')
-rw-r--r-- | drivers/media/common/Kconfig | 3 | ||||
-rw-r--r-- | drivers/media/common/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/common/cypress_firmware.c | 132 | ||||
-rw-r--r-- | drivers/media/common/cypress_firmware.h | 28 |
4 files changed, 164 insertions, 0 deletions
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig index 56c25e6299e9..ba666c707d58 100644 --- a/drivers/media/common/Kconfig +++ b/drivers/media/common/Kconfig | |||
@@ -16,6 +16,9 @@ config VIDEO_TVEEPROM | |||
16 | tristate | 16 | tristate |
17 | depends on I2C | 17 | depends on I2C |
18 | 18 | ||
19 | config CYPRESS_FIRMWARE | ||
20 | tristate "Cypress firmware helper routines" | ||
21 | |||
19 | source "drivers/media/common/b2c2/Kconfig" | 22 | source "drivers/media/common/b2c2/Kconfig" |
20 | source "drivers/media/common/saa7146/Kconfig" | 23 | source "drivers/media/common/saa7146/Kconfig" |
21 | source "drivers/media/common/siano/Kconfig" | 24 | source "drivers/media/common/siano/Kconfig" |
diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile index 8f8d18755d15..d208de3b7cc0 100644 --- a/drivers/media/common/Makefile +++ b/drivers/media/common/Makefile | |||
@@ -2,3 +2,4 @@ obj-y += b2c2/ saa7146/ siano/ | |||
2 | obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o | 2 | obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o |
3 | obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o | 3 | obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o |
4 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o | 4 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o |
5 | obj-$(CONFIG_CYPRESS_FIRMWARE) += cypress_firmware.o | ||
diff --git a/drivers/media/common/cypress_firmware.c b/drivers/media/common/cypress_firmware.c new file mode 100644 index 000000000000..577e82058fdc --- /dev/null +++ b/drivers/media/common/cypress_firmware.c | |||
@@ -0,0 +1,132 @@ | |||
1 | /* cypress_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 <linux/module.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/usb.h> | ||
14 | #include <linux/firmware.h> | ||
15 | #include "cypress_firmware.h" | ||
16 | |||
17 | struct usb_cypress_controller { | ||
18 | u8 id; | ||
19 | const char *name; /* name of the usb controller */ | ||
20 | u16 cs_reg; /* needs to be restarted, | ||
21 | * when the firmware has been downloaded */ | ||
22 | }; | ||
23 | |||
24 | static const struct usb_cypress_controller cypress[] = { | ||
25 | { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cs_reg = 0x7f92 }, | ||
26 | { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cs_reg = 0x7f92 }, | ||
27 | { .id = CYPRESS_FX2, .name = "Cypress FX2", .cs_reg = 0xe600 }, | ||
28 | }; | ||
29 | |||
30 | /* | ||
31 | * load a firmware packet to the device | ||
32 | */ | ||
33 | static int usb_cypress_writemem(struct usb_device *udev, u16 addr, u8 *data, | ||
34 | u8 len) | ||
35 | { | ||
36 | return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
37 | 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000); | ||
38 | } | ||
39 | |||
40 | static int cypress_get_hexline(const struct firmware *fw, | ||
41 | struct hexline *hx, int *pos) | ||
42 | { | ||
43 | u8 *b = (u8 *) &fw->data[*pos]; | ||
44 | int data_offs = 4; | ||
45 | |||
46 | if (*pos >= fw->size) | ||
47 | return 0; | ||
48 | |||
49 | memset(hx, 0, sizeof(struct hexline)); | ||
50 | hx->len = b[0]; | ||
51 | |||
52 | if ((*pos + hx->len + 4) >= fw->size) | ||
53 | return -EINVAL; | ||
54 | |||
55 | hx->addr = b[1] | (b[2] << 8); | ||
56 | hx->type = b[3]; | ||
57 | |||
58 | if (hx->type == 0x04) { | ||
59 | /* b[4] and b[5] are the Extended linear address record data | ||
60 | * field */ | ||
61 | hx->addr |= (b[4] << 24) | (b[5] << 16); | ||
62 | } | ||
63 | |||
64 | memcpy(hx->data, &b[data_offs], hx->len); | ||
65 | hx->chk = b[hx->len + data_offs]; | ||
66 | *pos += hx->len + 5; | ||
67 | |||
68 | return *pos; | ||
69 | } | ||
70 | |||
71 | int cypress_load_firmware(struct usb_device *udev, | ||
72 | const struct firmware *fw, int type) | ||
73 | { | ||
74 | struct hexline *hx; | ||
75 | int ret, pos = 0; | ||
76 | |||
77 | hx = kmalloc(sizeof(struct hexline), GFP_KERNEL); | ||
78 | if (!hx) { | ||
79 | dev_err(&udev->dev, "%s: kmalloc() failed\n", KBUILD_MODNAME); | ||
80 | return -ENOMEM; | ||
81 | } | ||
82 | |||
83 | /* stop the CPU */ | ||
84 | hx->data[0] = 1; | ||
85 | ret = usb_cypress_writemem(udev, cypress[type].cs_reg, hx->data, 1); | ||
86 | if (ret != 1) { | ||
87 | dev_err(&udev->dev, "%s: CPU stop failed=%d\n", | ||
88 | KBUILD_MODNAME, ret); | ||
89 | ret = -EIO; | ||
90 | goto err_kfree; | ||
91 | } | ||
92 | |||
93 | /* write firmware to memory */ | ||
94 | for (;;) { | ||
95 | ret = cypress_get_hexline(fw, hx, &pos); | ||
96 | if (ret < 0) | ||
97 | goto err_kfree; | ||
98 | else if (ret == 0) | ||
99 | break; | ||
100 | |||
101 | ret = usb_cypress_writemem(udev, hx->addr, hx->data, hx->len); | ||
102 | if (ret < 0) { | ||
103 | goto err_kfree; | ||
104 | } else if (ret != hx->len) { | ||
105 | dev_err(&udev->dev, | ||
106 | "%s: error while transferring firmware (transferred size=%d, block size=%d)\n", | ||
107 | KBUILD_MODNAME, ret, hx->len); | ||
108 | ret = -EIO; | ||
109 | goto err_kfree; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | /* start the CPU */ | ||
114 | hx->data[0] = 0; | ||
115 | ret = usb_cypress_writemem(udev, cypress[type].cs_reg, hx->data, 1); | ||
116 | if (ret != 1) { | ||
117 | dev_err(&udev->dev, "%s: CPU start failed=%d\n", | ||
118 | KBUILD_MODNAME, ret); | ||
119 | ret = -EIO; | ||
120 | goto err_kfree; | ||
121 | } | ||
122 | |||
123 | ret = 0; | ||
124 | err_kfree: | ||
125 | kfree(hx); | ||
126 | return ret; | ||
127 | } | ||
128 | EXPORT_SYMBOL(cypress_load_firmware); | ||
129 | |||
130 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
131 | MODULE_DESCRIPTION("Cypress firmware download"); | ||
132 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/cypress_firmware.h b/drivers/media/common/cypress_firmware.h new file mode 100644 index 000000000000..e493cbc7a528 --- /dev/null +++ b/drivers/media/common/cypress_firmware.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
3 | * see dvb-usb-init.c for copyright information. | ||
4 | * | ||
5 | * This file contains functions for downloading the firmware to Cypress FX 1 | ||
6 | * and 2 based devices. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #ifndef CYPRESS_FIRMWARE_H | ||
11 | #define CYPRESS_FIRMWARE_H | ||
12 | |||
13 | #define CYPRESS_AN2135 0 | ||
14 | #define CYPRESS_AN2235 1 | ||
15 | #define CYPRESS_FX2 2 | ||
16 | |||
17 | /* commonly used firmware download types and function */ | ||
18 | struct hexline { | ||
19 | u8 len; | ||
20 | u32 addr; | ||
21 | u8 type; | ||
22 | u8 data[255]; | ||
23 | u8 chk; | ||
24 | }; | ||
25 | |||
26 | int cypress_load_firmware(struct usb_device *, const struct firmware *, int); | ||
27 | |||
28 | #endif | ||