diff options
Diffstat (limited to 'drivers/media/video/cx18/cx18-firmware.c')
| -rw-r--r-- | drivers/media/video/cx18/cx18-firmware.c | 54 |
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 | ||
| 103 | static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx, long size) | 99 | static 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 | ||
| 111 | retry: | 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 | ||
| 152 | static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx, long size) | 136 | static 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 | ||
| 164 | retry: | 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; |
