aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-firmware.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx18/cx18-firmware.c')
-rw-r--r--drivers/media/video/cx18/cx18-firmware.c54
1 files changed, 13 insertions, 41 deletions
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c
index 2d630d9f7496..78fadd2ada5d 100644
--- a/drivers/media/video/cx18/cx18-firmware.c
+++ b/drivers/media/video/cx18/cx18-firmware.c
@@ -86,10 +86,6 @@
86 86
87#define CX18_DSP0_INTERRUPT_MASK 0xd0004C 87#define CX18_DSP0_INTERRUPT_MASK 0xd0004C
88 88
89/* Encoder/decoder firmware sizes */
90#define CX18_FW_CPU_SIZE (158332)
91#define CX18_FW_APU_SIZE (141200)
92
93#define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */ 89#define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */
94#define APU_ROM_SYNC2 0x72646548 /* "rdeH" */ 90#define APU_ROM_SYNC2 0x72646548 /* "rdeH" */
95 91
@@ -100,35 +96,22 @@ struct cx18_apu_rom_seghdr {
100 u32 size; 96 u32 size;
101}; 97};
102 98
103static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx, long size) 99static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
104{ 100{
105 const struct firmware *fw = NULL; 101 const struct firmware *fw = NULL;
106 int retries = 3;
107 int i, j; 102 int i, j;
103 unsigned size;
108 u32 __iomem *dst = (u32 __iomem *)mem; 104 u32 __iomem *dst = (u32 __iomem *)mem;
109 const u32 *src; 105 const u32 *src;
110 106
111retry: 107 if (request_firmware(&fw, fn, &cx->dev->dev)) {
112 if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) { 108 CX18_ERR("Unable to open firmware %s\n", fn);
113 CX18_ERR("Unable to open firmware %s (must be %ld bytes)\n",
114 fn, size);
115 CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n"); 109 CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");
116 return -ENOMEM; 110 return -ENOMEM;
117 } 111 }
118 112
119 src = (const u32 *)fw->data; 113 src = (const u32 *)fw->data;
120 114
121 if (fw->size != size) {
122 /* Due to race conditions in firmware loading (esp. with
123 udev <0.95) the wrong file was sometimes loaded. So we check
124 filesizes to see if at least the right-sized file was
125 loaded. If not, then we retry. */
126 CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
127 fn, size, fw->size);
128 release_firmware(fw);
129 retries--;
130 goto retry;
131 }
132 for (i = 0; i < fw->size; i += 4096) { 115 for (i = 0; i < fw->size; i += 4096) {
133 setup_page(i); 116 setup_page(i);
134 for (j = i; j < fw->size && j < i + 4096; j += 4) { 117 for (j = i; j < fw->size && j < i + 4096; j += 4) {
@@ -145,15 +128,16 @@ retry:
145 } 128 }
146 if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags)) 129 if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
147 CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size); 130 CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size);
131 size = fw->size;
148 release_firmware(fw); 132 release_firmware(fw);
149 return size; 133 return size;
150} 134}
151 135
152static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx, long size) 136static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
153{ 137{
154 const struct firmware *fw = NULL; 138 const struct firmware *fw = NULL;
155 int retries = 3;
156 int i, j; 139 int i, j;
140 unsigned size;
157 const u32 *src; 141 const u32 *src;
158 struct cx18_apu_rom_seghdr seghdr; 142 struct cx18_apu_rom_seghdr seghdr;
159 const u8 *vers; 143 const u8 *vers;
@@ -161,10 +145,8 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
161 u32 apu_version = 0; 145 u32 apu_version = 0;
162 int sz; 146 int sz;
163 147
164retry: 148 if (request_firmware(&fw, fn, &cx->dev->dev)) {
165 if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) { 149 CX18_ERR("unable to open firmware %s\n", fn);
166 CX18_ERR("unable to open firmware %s (must be %ld bytes)\n",
167 fn, size);
168 CX18_ERR("did you put the firmware in the hotplug firmware directory?\n"); 150 CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
169 return -ENOMEM; 151 return -ENOMEM;
170 } 152 }
@@ -173,19 +155,8 @@ retry:
173 vers = fw->data + sizeof(seghdr); 155 vers = fw->data + sizeof(seghdr);
174 sz = fw->size; 156 sz = fw->size;
175 157
176 if (fw->size != size) {
177 /* Due to race conditions in firmware loading (esp. with
178 udev <0.95) the wrong file was sometimes loaded. So we check
179 filesizes to see if at least the right-sized file was
180 loaded. If not, then we retry. */
181 CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
182 fn, size, fw->size);
183 release_firmware(fw);
184 retries--;
185 goto retry;
186 }
187 apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32]; 158 apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];
188 while (offset + sizeof(seghdr) < size) { 159 while (offset + sizeof(seghdr) < fw->size) {
189 /* TODO: byteswapping */ 160 /* TODO: byteswapping */
190 memcpy(&seghdr, src + offset / 4, sizeof(seghdr)); 161 memcpy(&seghdr, src + offset / 4, sizeof(seghdr));
191 offset += sizeof(seghdr); 162 offset += sizeof(seghdr);
@@ -215,6 +186,7 @@ retry:
215 if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags)) 186 if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
216 CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n", 187 CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n",
217 fn, apu_version, fw->size); 188 fn, apu_version, fw->size);
189 size = fw->size;
218 release_firmware(fw); 190 release_firmware(fw);
219 /* Clear bit0 for APU to start from 0 */ 191 /* Clear bit0 for APU to start from 0 */
220 write_reg(read_reg(0xc72030) & ~1, 0xc72030); 192 write_reg(read_reg(0xc72030) & ~1, 0xc72030);
@@ -340,7 +312,7 @@ int cx18_firmware_init(struct cx18 *cx)
340 /* Only if the processor is not running */ 312 /* Only if the processor is not running */
341 if (read_reg(CX18_PROC_SOFT_RESET) & 8) { 313 if (read_reg(CX18_PROC_SOFT_RESET) & 8) {
342 int sz = load_apu_fw_direct("v4l-cx23418-apu.fw", 314 int sz = load_apu_fw_direct("v4l-cx23418-apu.fw",
343 cx->enc_mem, cx, CX18_FW_APU_SIZE); 315 cx->enc_mem, cx);
344 316
345 write_enc(0xE51FF004, 0); 317 write_enc(0xE51FF004, 0);
346 write_enc(0xa00000, 4); /* todo: not hardcoded */ 318 write_enc(0xa00000, 4); /* todo: not hardcoded */
@@ -348,7 +320,7 @@ int cx18_firmware_init(struct cx18 *cx)
348 cx18_msleep_timeout(500, 0); 320 cx18_msleep_timeout(500, 0);
349 321
350 sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw", 322 sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
351 cx->enc_mem, cx, CX18_FW_CPU_SIZE); 323 cx->enc_mem, cx);
352 324
353 if (sz > 0) { 325 if (sz > 0) {
354 int retries = 0; 326 int retries = 0;