diff options
author | Andy Walls <awalls@radix.net> | 2008-11-02 08:59:04 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-29 14:53:26 -0500 |
commit | ced07371d931884c9c89b66bfe951ea0148a8d08 (patch) | |
tree | 607a83c66ff40f43bb9ce28839cb5ff9c35736a5 /drivers/media/video/cx18/cx18-firmware.c | |
parent | 48fc6bb37ba8ee278a8cc647a4ef2bf529b519dd (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.c | 60 |
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) | |||
200 | void cx18_halt_firmware(struct cx18 *cx) | 200 | void 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 | ||
207 | void cx18_init_power(struct cx18 *cx, int lowpwr) | 209 | void 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 | ||
263 | void cx18_init_memory(struct cx18 *cx) | 277 | void 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 | } |