diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2009-08-31 16:57:52 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-12 11:19:52 -0400 |
commit | 8d81ae243158b0ac8b2c1646d5adcbdf26a260bc (patch) | |
tree | 9205ec200ec17a4a32c2a6f5dc043dd43446afb5 /drivers/media/video/cx25840 | |
parent | a65f3159244f27ce6ff84dd1bb641079acdbd396 (diff) |
V4L/DVB (12613): cx25840: fix determining the firmware name
Depending on the model there are three different firmwares to choose from.
Unfortunately if a cx23885 is loaded first, then the global firmware name
is overwritten with that firmware and if ivtv is loaded next, then it
tries to load the wrong firmware. In addition, the original approach would
also overwrite any firmware that the user specified explicitly.
Cc: Jarod Wilson <jarod@wilsonet.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx25840')
-rw-r--r-- | drivers/media/video/cx25840/cx25840-firmware.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index 2a535d0403ed..1f483c1d0dbe 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c | |||
@@ -23,10 +23,6 @@ | |||
23 | 23 | ||
24 | #include "cx25840-core.h" | 24 | #include "cx25840-core.h" |
25 | 25 | ||
26 | #define FWFILE "v4l-cx25840.fw" | ||
27 | #define FWFILE_CX23885 "v4l-cx23885-avcore-01.fw" | ||
28 | #define FWFILE_CX231XX "v4l-cx231xx-avcore-01.fw" | ||
29 | |||
30 | /* | 26 | /* |
31 | * Mike Isely <isely@pobox.com> - The FWSEND parameter controls the | 27 | * Mike Isely <isely@pobox.com> - The FWSEND parameter controls the |
32 | * size of the firmware chunks sent down the I2C bus to the chip. | 28 | * size of the firmware chunks sent down the I2C bus to the chip. |
@@ -40,11 +36,11 @@ | |||
40 | 36 | ||
41 | #define FWDEV(x) &((x)->dev) | 37 | #define FWDEV(x) &((x)->dev) |
42 | 38 | ||
43 | static char *firmware = FWFILE; | 39 | static char *firmware = ""; |
44 | 40 | ||
45 | module_param(firmware, charp, 0444); | 41 | module_param(firmware, charp, 0444); |
46 | 42 | ||
47 | MODULE_PARM_DESC(firmware, "Firmware image [default: " FWFILE "]"); | 43 | MODULE_PARM_DESC(firmware, "Firmware image to load"); |
48 | 44 | ||
49 | static void start_fw_load(struct i2c_client *client) | 45 | static void start_fw_load(struct i2c_client *client) |
50 | { | 46 | { |
@@ -65,6 +61,19 @@ static void end_fw_load(struct i2c_client *client) | |||
65 | cx25840_write(client, 0x803, 0x03); | 61 | cx25840_write(client, 0x803, 0x03); |
66 | } | 62 | } |
67 | 63 | ||
64 | static const char *get_fw_name(struct i2c_client *client) | ||
65 | { | ||
66 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | ||
67 | |||
68 | if (firmware[0]) | ||
69 | return firmware; | ||
70 | if (state->is_cx23885) | ||
71 | return "v4l-cx23885-avcore-01.fw"; | ||
72 | if (state->is_cx231xx) | ||
73 | return "v4l-cx231xx-avcore-01.fw"; | ||
74 | return "v4l-cx25840.fw"; | ||
75 | } | ||
76 | |||
68 | static int check_fw_load(struct i2c_client *client, int size) | 77 | static int check_fw_load(struct i2c_client *client, int size) |
69 | { | 78 | { |
70 | /* DL_ADDR_HB DL_ADDR_LB */ | 79 | /* DL_ADDR_HB DL_ADDR_LB */ |
@@ -72,11 +81,13 @@ static int check_fw_load(struct i2c_client *client, int size) | |||
72 | s |= cx25840_read(client, 0x800); | 81 | s |= cx25840_read(client, 0x800); |
73 | 82 | ||
74 | if (size != s) { | 83 | if (size != s) { |
75 | v4l_err(client, "firmware %s load failed\n", firmware); | 84 | v4l_err(client, "firmware %s load failed\n", |
85 | get_fw_name(client)); | ||
76 | return -EINVAL; | 86 | return -EINVAL; |
77 | } | 87 | } |
78 | 88 | ||
79 | v4l_info(client, "loaded %s firmware (%d bytes)\n", firmware, size); | 89 | v4l_info(client, "loaded %s firmware (%d bytes)\n", |
90 | get_fw_name(client), size); | ||
80 | return 0; | 91 | return 0; |
81 | } | 92 | } |
82 | 93 | ||
@@ -96,26 +107,24 @@ int cx25840_loadfw(struct i2c_client *client) | |||
96 | const struct firmware *fw = NULL; | 107 | const struct firmware *fw = NULL; |
97 | u8 buffer[FWSEND]; | 108 | u8 buffer[FWSEND]; |
98 | const u8 *ptr; | 109 | const u8 *ptr; |
110 | const char *fwname = get_fw_name(client); | ||
99 | int size, retval; | 111 | int size, retval; |
100 | int MAX_BUF_SIZE = FWSEND; | 112 | int MAX_BUF_SIZE = FWSEND; |
101 | u32 gpio_oe = 0, gpio_da = 0; | 113 | u32 gpio_oe = 0, gpio_da = 0; |
102 | 114 | ||
103 | if (state->is_cx23885) { | 115 | if (state->is_cx23885) { |
104 | firmware = FWFILE_CX23885; | ||
105 | /* Preserve the GPIO OE and output bits */ | 116 | /* Preserve the GPIO OE and output bits */ |
106 | gpio_oe = cx25840_read(client, 0x160); | 117 | gpio_oe = cx25840_read(client, 0x160); |
107 | gpio_da = cx25840_read(client, 0x164); | 118 | gpio_da = cx25840_read(client, 0x164); |
108 | } | 119 | } |
109 | else if (state->is_cx231xx) | ||
110 | firmware = FWFILE_CX231XX; | ||
111 | 120 | ||
112 | if ((state->is_cx231xx) && MAX_BUF_SIZE > 16) { | 121 | if ((state->is_cx231xx) && MAX_BUF_SIZE > 16) { |
113 | v4l_err(client, " Firmware download size changed to 16 bytes max length\n"); | 122 | v4l_err(client, " Firmware download size changed to 16 bytes max length\n"); |
114 | MAX_BUF_SIZE = 16; /* cx231xx cannot accept more than 16 bytes at a time */ | 123 | MAX_BUF_SIZE = 16; /* cx231xx cannot accept more than 16 bytes at a time */ |
115 | } | 124 | } |
116 | 125 | ||
117 | if (request_firmware(&fw, firmware, FWDEV(client)) != 0) { | 126 | if (request_firmware(&fw, fwname, FWDEV(client)) != 0) { |
118 | v4l_err(client, "unable to open firmware %s\n", firmware); | 127 | v4l_err(client, "unable to open firmware %s\n", fwname); |
119 | return -EINVAL; | 128 | return -EINVAL; |
120 | } | 129 | } |
121 | 130 | ||