This source file includes following definitions.
- load_cpu_fw_direct
- load_apu_fw_direct
- cx18_halt_firmware
- cx18_init_power
- cx18_init_memory
- cx18_firmware_init
1
2
3
4
5
6
7
8
9 #include "cx18-driver.h"
10 #include "cx18-io.h"
11 #include "cx18-scb.h"
12 #include "cx18-irq.h"
13 #include "cx18-firmware.h"
14 #include "cx18-cards.h"
15 #include <linux/firmware.h>
16
17 #define CX18_PROC_SOFT_RESET 0xc70010
18 #define CX18_DDR_SOFT_RESET 0xc70014
19 #define CX18_CLOCK_SELECT1 0xc71000
20 #define CX18_CLOCK_SELECT2 0xc71004
21 #define CX18_HALF_CLOCK_SELECT1 0xc71008
22 #define CX18_HALF_CLOCK_SELECT2 0xc7100C
23 #define CX18_CLOCK_POLARITY1 0xc71010
24 #define CX18_CLOCK_POLARITY2 0xc71014
25 #define CX18_ADD_DELAY_ENABLE1 0xc71018
26 #define CX18_ADD_DELAY_ENABLE2 0xc7101C
27 #define CX18_CLOCK_ENABLE1 0xc71020
28 #define CX18_CLOCK_ENABLE2 0xc71024
29
30 #define CX18_REG_BUS_TIMEOUT_EN 0xc72024
31
32 #define CX18_FAST_CLOCK_PLL_INT 0xc78000
33 #define CX18_FAST_CLOCK_PLL_FRAC 0xc78004
34 #define CX18_FAST_CLOCK_PLL_POST 0xc78008
35 #define CX18_FAST_CLOCK_PLL_PRESCALE 0xc7800C
36 #define CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH 0xc78010
37
38 #define CX18_SLOW_CLOCK_PLL_INT 0xc78014
39 #define CX18_SLOW_CLOCK_PLL_FRAC 0xc78018
40 #define CX18_SLOW_CLOCK_PLL_POST 0xc7801C
41 #define CX18_MPEG_CLOCK_PLL_INT 0xc78040
42 #define CX18_MPEG_CLOCK_PLL_FRAC 0xc78044
43 #define CX18_MPEG_CLOCK_PLL_POST 0xc78048
44 #define CX18_PLL_POWER_DOWN 0xc78088
45 #define CX18_SW1_INT_STATUS 0xc73104
46 #define CX18_SW1_INT_ENABLE_PCI 0xc7311C
47 #define CX18_SW2_INT_SET 0xc73140
48 #define CX18_SW2_INT_STATUS 0xc73144
49 #define CX18_ADEC_CONTROL 0xc78120
50
51 #define CX18_DDR_REQUEST_ENABLE 0xc80000
52 #define CX18_DDR_CHIP_CONFIG 0xc80004
53 #define CX18_DDR_REFRESH 0xc80008
54 #define CX18_DDR_TIMING1 0xc8000C
55 #define CX18_DDR_TIMING2 0xc80010
56 #define CX18_DDR_POWER_REG 0xc8001C
57
58 #define CX18_DDR_TUNE_LANE 0xc80048
59 #define CX18_DDR_INITIAL_EMRS 0xc80054
60 #define CX18_DDR_MB_PER_ROW_7 0xc8009C
61 #define CX18_DDR_BASE_63_ADDR 0xc804FC
62
63 #define CX18_WMB_CLIENT02 0xc90108
64 #define CX18_WMB_CLIENT05 0xc90114
65 #define CX18_WMB_CLIENT06 0xc90118
66 #define CX18_WMB_CLIENT07 0xc9011C
67 #define CX18_WMB_CLIENT08 0xc90120
68 #define CX18_WMB_CLIENT09 0xc90124
69 #define CX18_WMB_CLIENT10 0xc90128
70 #define CX18_WMB_CLIENT11 0xc9012C
71 #define CX18_WMB_CLIENT12 0xc90130
72 #define CX18_WMB_CLIENT13 0xc90134
73 #define CX18_WMB_CLIENT14 0xc90138
74
75 #define CX18_DSP0_INTERRUPT_MASK 0xd0004C
76
77 #define APU_ROM_SYNC1 0x6D676553
78 #define APU_ROM_SYNC2 0x72646548
79
80 struct cx18_apu_rom_seghdr {
81 u32 sync1;
82 u32 sync2;
83 u32 addr;
84 u32 size;
85 };
86
87 static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
88 {
89 const struct firmware *fw = NULL;
90 int i, j;
91 unsigned size;
92 u32 __iomem *dst = (u32 __iomem *)mem;
93 const u32 *src;
94
95 if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {
96 CX18_ERR("Unable to open firmware %s\n", fn);
97 CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");
98 return -ENOMEM;
99 }
100
101 src = (const u32 *)fw->data;
102
103 for (i = 0; i < fw->size; i += 4096) {
104 cx18_setup_page(cx, i);
105 for (j = i; j < fw->size && j < i + 4096; j += 4) {
106
107 cx18_raw_writel(cx, *src, dst);
108 if (cx18_raw_readl(cx, dst) != *src) {
109 CX18_ERR("Mismatch at offset %x\n", i);
110 release_firmware(fw);
111 cx18_setup_page(cx, 0);
112 return -EIO;
113 }
114 dst++;
115 src++;
116 }
117 }
118 if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
119 CX18_INFO("loaded %s firmware (%zu bytes)\n", fn, fw->size);
120 size = fw->size;
121 release_firmware(fw);
122 cx18_setup_page(cx, SCB_OFFSET);
123 return size;
124 }
125
126 static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
127 u32 *entry_addr)
128 {
129 const struct firmware *fw = NULL;
130 int i, j;
131 unsigned size;
132 const u32 *src;
133 struct cx18_apu_rom_seghdr seghdr;
134 const u8 *vers;
135 u32 offset = 0;
136 u32 apu_version = 0;
137 int sz;
138
139 if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {
140 CX18_ERR("unable to open firmware %s\n", fn);
141 CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
142 cx18_setup_page(cx, 0);
143 return -ENOMEM;
144 }
145
146 *entry_addr = 0;
147 src = (const u32 *)fw->data;
148 vers = fw->data + sizeof(seghdr);
149 sz = fw->size;
150
151 apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];
152 while (offset + sizeof(seghdr) < fw->size) {
153 const __le32 *shptr = (__force __le32 *)src + offset / 4;
154
155 seghdr.sync1 = le32_to_cpu(shptr[0]);
156 seghdr.sync2 = le32_to_cpu(shptr[1]);
157 seghdr.addr = le32_to_cpu(shptr[2]);
158 seghdr.size = le32_to_cpu(shptr[3]);
159
160 offset += sizeof(seghdr);
161 if (seghdr.sync1 != APU_ROM_SYNC1 ||
162 seghdr.sync2 != APU_ROM_SYNC2) {
163 offset += seghdr.size;
164 continue;
165 }
166 CX18_DEBUG_INFO("load segment %x-%x\n", seghdr.addr,
167 seghdr.addr + seghdr.size - 1);
168 if (*entry_addr == 0)
169 *entry_addr = seghdr.addr;
170 if (offset + seghdr.size > sz)
171 break;
172 for (i = 0; i < seghdr.size; i += 4096) {
173 cx18_setup_page(cx, seghdr.addr + i);
174 for (j = i; j < seghdr.size && j < i + 4096; j += 4) {
175
176 cx18_raw_writel(cx, src[(offset + j) / 4],
177 dst + seghdr.addr + j);
178 if (cx18_raw_readl(cx, dst + seghdr.addr + j)
179 != src[(offset + j) / 4]) {
180 CX18_ERR("Mismatch at offset %x\n",
181 offset + j);
182 release_firmware(fw);
183 cx18_setup_page(cx, 0);
184 return -EIO;
185 }
186 }
187 }
188 offset += seghdr.size;
189 }
190 if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
191 CX18_INFO("loaded %s firmware V%08x (%zu bytes)\n",
192 fn, apu_version, fw->size);
193 size = fw->size;
194 release_firmware(fw);
195 cx18_setup_page(cx, 0);
196 return size;
197 }
198
199 void cx18_halt_firmware(struct cx18 *cx)
200 {
201 CX18_DEBUG_INFO("Preparing for firmware halt.\n");
202 cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
203 0x0000000F, 0x000F000F);
204 cx18_write_reg_expect(cx, 0x00020002, CX18_ADEC_CONTROL,
205 0x00000002, 0x00020002);
206 }
207
208 void cx18_init_power(struct cx18 *cx, int lowpwr)
209 {
210
211
212 cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN);
213
214
215 cx18_write_reg_expect(cx, 0x00020000, CX18_ADEC_CONTROL,
216 0x00000000, 0x00020002);
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257 cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
258 cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7,
259 CX18_FAST_CLOCK_PLL_FRAC);
260
261 cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST);
262 cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE);
263 cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
264
265
266
267
268 cx18_write_reg(cx, lowpwr ? 0xD : 0xC, CX18_SLOW_CLOCK_PLL_INT);
269 cx18_write_reg(cx, lowpwr ? 0x30C344 : 0x124927F,
270 CX18_SLOW_CLOCK_PLL_FRAC);
271 cx18_write_reg(cx, 3, CX18_SLOW_CLOCK_PLL_POST);
272
273
274
275 cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT);
276 cx18_write_reg(cx, 0x2BE2FE, CX18_MPEG_CLOCK_PLL_FRAC);
277 cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST);
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294 if (lowpwr) {
295 cx18_write_reg_expect(cx, 0xFFFF0020, CX18_CLOCK_SELECT1,
296 0x00000020, 0xFFFFFFFF);
297 cx18_write_reg_expect(cx, 0xFFFF0004, CX18_CLOCK_SELECT2,
298 0x00000004, 0xFFFFFFFF);
299 } else {
300
301 cx18_write_reg_expect(cx, 0x00060004, CX18_CLOCK_SELECT1,
302 0x00000004, 0x00060006);
303 cx18_write_reg_expect(cx, 0x00060006, CX18_CLOCK_SELECT2,
304 0x00000006, 0x00060006);
305 }
306
307 cx18_write_reg_expect(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1,
308 0x00000002, 0xFFFFFFFF);
309 cx18_write_reg_expect(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2,
310 0x00000104, 0xFFFFFFFF);
311 cx18_write_reg_expect(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1,
312 0x00009026, 0xFFFFFFFF);
313 cx18_write_reg_expect(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2,
314 0x00003105, 0xFFFFFFFF);
315 }
316
317 void cx18_init_memory(struct cx18 *cx)
318 {
319 cx18_msleep_timeout(10, 0);
320 cx18_write_reg_expect(cx, 0x00010000, CX18_DDR_SOFT_RESET,
321 0x00000000, 0x00010001);
322 cx18_msleep_timeout(10, 0);
323
324 cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
325
326 cx18_msleep_timeout(10, 0);
327
328 cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH);
329 cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1);
330 cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2);
331
332 cx18_msleep_timeout(10, 0);
333
334
335 cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
336 cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
337
338 cx18_msleep_timeout(10, 0);
339
340 cx18_write_reg_expect(cx, 0x00020000, CX18_DDR_SOFT_RESET,
341 0x00000000, 0x00020002);
342 cx18_msleep_timeout(10, 0);
343
344
345 cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG);
346
347 cx18_write_reg_expect(cx, 0x00010001, CX18_REG_BUS_TIMEOUT_EN,
348 0x00000001, 0x00010001);
349
350 cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7);
351 cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR);
352
353 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02);
354 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09);
355 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05);
356 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06);
357 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07);
358 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10);
359 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12);
360 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13);
361 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11);
362 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14);
363 }
364
365 #define CX18_CPU_FIRMWARE "v4l-cx23418-cpu.fw"
366 #define CX18_APU_FIRMWARE "v4l-cx23418-apu.fw"
367
368 int cx18_firmware_init(struct cx18 *cx)
369 {
370 u32 fw_entry_addr;
371 int sz, retries;
372 u32 api_args[MAX_MB_ARGUMENTS];
373
374
375 cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);
376
377
378 cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
379 0x0000000F, 0x000F000F);
380
381 cx18_msleep_timeout(1, 0);
382
383
384 if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) == 0) {
385 CX18_ERR("%s: couldn't stop CPU to load firmware\n", __func__);
386 return -EIO;
387 }
388
389 cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
390 cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
391
392 sz = load_cpu_fw_direct(CX18_CPU_FIRMWARE, cx->enc_mem, cx);
393 if (sz <= 0)
394 return sz;
395
396
397 cx18_init_scb(cx);
398
399 fw_entry_addr = 0;
400 sz = load_apu_fw_direct(CX18_APU_FIRMWARE, cx->enc_mem, cx,
401 &fw_entry_addr);
402 if (sz <= 0)
403 return sz;
404
405
406 cx18_write_reg_expect(cx, 0x00080000, CX18_PROC_SOFT_RESET,
407 0x00000000, 0x00080008);
408
409
410 for (retries = 0;
411 retries < 50 && (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1;
412 retries++)
413 cx18_msleep_timeout(10, 0);
414
415 cx18_msleep_timeout(200, 0);
416
417 if (retries == 50 &&
418 (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1) {
419 CX18_ERR("Could not start the CPU\n");
420 return -EIO;
421 }
422
423
424
425
426
427
428
429
430
431
432 cx18_sw2_irq_disable_cpu(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
433
434
435 sz = cx18_vapi_result(cx, api_args, CX18_CPU_DEBUG_PEEK32, 1, 0);
436 if (sz < 0)
437 return sz;
438
439
440 cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400);
441 return 0;
442 }
443
444 MODULE_FIRMWARE(CX18_CPU_FIRMWARE);
445 MODULE_FIRMWARE(CX18_APU_FIRMWARE);