aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-firmware.c
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2008-11-02 08:59:04 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-29 14:53:26 -0500
commitced07371d931884c9c89b66bfe951ea0148a8d08 (patch)
tree607a83c66ff40f43bb9ce28839cb5ff9c35736a5 /drivers/media/video/cx18/cx18-firmware.c
parent48fc6bb37ba8ee278a8cc647a4ef2bf529b519dd (diff)
V4L/DVB (9512): cx18: Fix write retries for registers that always change - part 3.
cx18: Fix write retries for registers that always change - part 3. Fix the io for the rest of the registers that will often not read back the value just written. Modified register readback checks to make sure the intended effect was achieved without constantly rewriting the registers. The one outstanding register remaining is 0xc72014 CX18_AUDIO_ENABLE, whose behavior on writes I have yet to determine. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18/cx18-firmware.c')
-rw-r--r--drivers/media/video/cx18/cx18-firmware.c60
1 files changed, 41 insertions, 19 deletions
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c
index 51534428cd00..7a7c89032caa 100644
--- a/drivers/media/video/cx18/cx18-firmware.c
+++ b/drivers/media/video/cx18/cx18-firmware.c
@@ -200,8 +200,10 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
200void cx18_halt_firmware(struct cx18 *cx) 200void cx18_halt_firmware(struct cx18 *cx)
201{ 201{
202 CX18_DEBUG_INFO("Preparing for firmware halt.\n"); 202 CX18_DEBUG_INFO("Preparing for firmware halt.\n");
203 cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ 203 cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
204 cx18_write_reg(cx, 0x00020002, CX18_ADEC_CONTROL); 204 0x0000000F, 0x000F000F);
205 cx18_write_reg_expect(cx, 0x00020002, CX18_ADEC_CONTROL,
206 0x00000002, 0x00020002);
205} 207}
206 208
207void cx18_init_power(struct cx18 *cx, int lowpwr) 209void cx18_init_power(struct cx18 *cx, int lowpwr)
@@ -211,7 +213,8 @@ void cx18_init_power(struct cx18 *cx, int lowpwr)
211 cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN); 213 cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN);
212 214
213 /* ADEC out of sleep */ 215 /* ADEC out of sleep */
214 cx18_write_reg(cx, 0x00020000, CX18_ADEC_CONTROL); 216 cx18_write_reg_expect(cx, 0x00020000, CX18_ADEC_CONTROL,
217 0x00000000, 0x00020002);
215 218
216 /* The fast clock is at 200/245 MHz */ 219 /* The fast clock is at 200/245 MHz */
217 cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT); 220 cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
@@ -248,22 +251,34 @@ void cx18_init_power(struct cx18 *cx, int lowpwr)
248 /* VFC = disabled */ 251 /* VFC = disabled */
249 /* USB = disabled */ 252 /* USB = disabled */
250 253
251 cx18_write_reg(cx, lowpwr ? 0xFFFF0020 : 0x00060004, 254 if (lowpwr) {
252 CX18_CLOCK_SELECT1); 255 cx18_write_reg_expect(cx, 0xFFFF0020, CX18_CLOCK_SELECT1,
253 cx18_write_reg(cx, lowpwr ? 0xFFFF0004 : 0x00060006, 256 0x00000020, 0xFFFFFFFF);
254 CX18_CLOCK_SELECT2); 257 cx18_write_reg_expect(cx, 0xFFFF0004, CX18_CLOCK_SELECT2,
255 258 0x00000004, 0xFFFFFFFF);
256 cx18_write_reg(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1); 259 } else {
257 cx18_write_reg(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2); 260 /* This doesn't explicitly set every clock select */
261 cx18_write_reg_expect(cx, 0x00060004, CX18_CLOCK_SELECT1,
262 0x00000004, 0x00060006);
263 cx18_write_reg_expect(cx, 0x00060006, CX18_CLOCK_SELECT2,
264 0x00000006, 0x00060006);
265 }
258 266
259 cx18_write_reg(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1); 267 cx18_write_reg_expect(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1,
260 cx18_write_reg(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2); 268 0x00000002, 0xFFFFFFFF);
269 cx18_write_reg_expect(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2,
270 0x00000104, 0xFFFFFFFF);
271 cx18_write_reg_expect(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1,
272 0x00009026, 0xFFFFFFFF);
273 cx18_write_reg_expect(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2,
274 0x00003105, 0xFFFFFFFF);
261} 275}
262 276
263void cx18_init_memory(struct cx18 *cx) 277void cx18_init_memory(struct cx18 *cx)
264{ 278{
265 cx18_msleep_timeout(10, 0); 279 cx18_msleep_timeout(10, 0);
266 cx18_write_reg(cx, 0x10000, CX18_DDR_SOFT_RESET); 280 cx18_write_reg_expect(cx, 0x00010000, CX18_DDR_SOFT_RESET,
281 0x00000000, 0x00010001);
267 cx18_msleep_timeout(10, 0); 282 cx18_msleep_timeout(10, 0);
268 283
269 cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG); 284 cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
@@ -282,13 +297,15 @@ void cx18_init_memory(struct cx18 *cx)
282 297
283 cx18_msleep_timeout(10, 0); 298 cx18_msleep_timeout(10, 0);
284 299
285 cx18_write_reg(cx, 0x20000, CX18_DDR_SOFT_RESET); 300 cx18_write_reg_expect(cx, 0x00020000, CX18_DDR_SOFT_RESET,
301 0x00000000, 0x00020002);
286 cx18_msleep_timeout(10, 0); 302 cx18_msleep_timeout(10, 0);
287 303
288 /* use power-down mode when idle */ 304 /* use power-down mode when idle */
289 cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG); 305 cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG);
290 306
291 cx18_write_reg(cx, 0x10001, CX18_REG_BUS_TIMEOUT_EN); 307 cx18_write_reg_expect(cx, 0x00010001, CX18_REG_BUS_TIMEOUT_EN,
308 0x00000001, 0x00010001);
292 309
293 cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7); 310 cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7);
294 cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR); 311 cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR);
@@ -310,7 +327,9 @@ int cx18_firmware_init(struct cx18 *cx)
310 /* Allow chip to control CLKRUN */ 327 /* Allow chip to control CLKRUN */
311 cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK); 328 cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);
312 329
313 cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ 330 /* Stop the firmware */
331 cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
332 0x0000000F, 0x000F000F);
314 333
315 cx18_msleep_timeout(1, 0); 334 cx18_msleep_timeout(1, 0);
316 335
@@ -325,7 +344,8 @@ int cx18_firmware_init(struct cx18 *cx)
325 cx18_write_enc(cx, 0xE51FF004, 0); 344 cx18_write_enc(cx, 0xE51FF004, 0);
326 cx18_write_enc(cx, 0xa00000, 4); /* todo: not hardcoded */ 345 cx18_write_enc(cx, 0xa00000, 4); /* todo: not hardcoded */
327 /* Start APU */ 346 /* Start APU */
328 cx18_write_reg(cx, 0x00010000, CX18_PROC_SOFT_RESET); 347 cx18_write_reg_expect(cx, 0x00010000, CX18_PROC_SOFT_RESET,
348 0x00000000, 0x00010001);
329 cx18_msleep_timeout(500, 0); 349 cx18_msleep_timeout(500, 0);
330 350
331 sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw", 351 sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
@@ -335,7 +355,9 @@ int cx18_firmware_init(struct cx18 *cx)
335 int retries = 0; 355 int retries = 0;
336 356
337 /* start the CPU */ 357 /* start the CPU */
338 cx18_write_reg(cx, 0x00080000, CX18_PROC_SOFT_RESET); 358 cx18_write_reg_expect(cx,
359 0x00080000, CX18_PROC_SOFT_RESET,
360 0x00000000, 0x00080008);
339 while (retries++ < 50) { /* Loop for max 500mS */ 361 while (retries++ < 50) { /* Loop for max 500mS */
340 if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) 362 if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET)
341 & 1) == 0) 363 & 1) == 0)
@@ -352,6 +374,6 @@ int cx18_firmware_init(struct cx18 *cx)
352 return -EIO; 374 return -EIO;
353 } 375 }
354 /* initialize GPIO */ 376 /* initialize GPIO */
355 cx18_write_reg(cx, 0x14001400, 0xC78110); 377 cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400);
356 return 0; 378 return 0;
357} 379}