Commit ced07371d931884c9c89b66bfe951ea0148a8d08

Authored by Andy Walls
Committed by Mauro Carvalho Chehab
1 parent 48fc6bb37b

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>

Showing 7 changed files with 185 additions and 80 deletions Side-by-side Diff

drivers/media/video/cx18/cx18-av-audio.c
... ... @@ -215,12 +215,15 @@
215 215 void cx18_av_audio_set_path(struct cx18 *cx)
216 216 {
217 217 struct cx18_av_state *state = &cx->av_state;
  218 + u8 v;
218 219  
219 220 /* stop microcontroller */
220   - cx18_av_and_or(cx, 0x803, ~0x10, 0);
  221 + v = cx18_av_read(cx, 0x803) & ~0x10;
  222 + cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
221 223  
222 224 /* assert soft reset */
223   - cx18_av_and_or(cx, 0x810, ~0x1, 0x01);
  225 + v = cx18_av_read(cx, 0x810) | 0x01;
  226 + cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
224 227  
225 228 /* Mute everything to prevent the PFFT! */
226 229 cx18_av_write(cx, 0x8d3, 0x1f);
227 230  
... ... @@ -240,12 +243,14 @@
240 243 set_audclk_freq(cx, state->audclk_freq);
241 244  
242 245 /* deassert soft reset */
243   - cx18_av_and_or(cx, 0x810, ~0x1, 0x00);
  246 + v = cx18_av_read(cx, 0x810) & ~0x01;
  247 + cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
244 248  
245 249 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
246 250 /* When the microcontroller detects the
247 251 * audio format, it will unmute the lines */
248   - cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
  252 + v = cx18_av_read(cx, 0x803) | 0x10;
  253 + cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
249 254 }
250 255 }
251 256  
252 257  
253 258  
254 259  
... ... @@ -347,19 +352,23 @@
347 352 static void set_mute(struct cx18 *cx, int mute)
348 353 {
349 354 struct cx18_av_state *state = &cx->av_state;
  355 + u8 v;
350 356  
351 357 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
352 358 /* Must turn off microcontroller in order to mute sound.
353 359 * Not sure if this is the best method, but it does work.
354 360 * If the microcontroller is running, then it will undo any
355 361 * changes to the mute register. */
  362 + v = cx18_av_read(cx, 0x803);
356 363 if (mute) {
357 364 /* disable microcontroller */
358   - cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
  365 + v &= ~0x10;
  366 + cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
359 367 cx18_av_write(cx, 0x8d3, 0x1f);
360 368 } else {
361 369 /* enable microcontroller */
362   - cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
  370 + v |= 0x10;
  371 + cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
363 372 }
364 373 } else {
365 374 /* SRC1_MUTE_EN */
366 375  
367 376  
368 377  
369 378  
... ... @@ -375,16 +384,26 @@
375 384  
376 385 switch (cmd) {
377 386 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
  387 + {
  388 + u8 v;
378 389 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
379   - cx18_av_and_or(cx, 0x803, ~0x10, 0);
  390 + v = cx18_av_read(cx, 0x803) & ~0x10;
  391 + cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
380 392 cx18_av_write(cx, 0x8d3, 0x1f);
381 393 }
382   - cx18_av_and_or(cx, 0x810, ~0x1, 1);
  394 + v = cx18_av_read(cx, 0x810) | 0x1;
  395 + cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
  396 +
383 397 retval = set_audclk_freq(cx, *(u32 *)arg);
384   - cx18_av_and_or(cx, 0x810, ~0x1, 0);
385   - if (state->aud_input > CX18_AV_AUDIO_SERIAL2)
386   - cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
  398 +
  399 + v = cx18_av_read(cx, 0x810) & ~0x1;
  400 + cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
  401 + if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
  402 + v = cx18_av_read(cx, 0x803) | 0x10;
  403 + cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
  404 + }
387 405 return retval;
  406 + }
388 407  
389 408 case VIDIOC_G_CTRL:
390 409 switch (ctrl->id) {
drivers/media/video/cx18/cx18-av-core.c
... ... @@ -36,12 +36,31 @@
36 36 return 0;
37 37 }
38 38  
  39 +int cx18_av_write_expect(struct cx18 *cx, u16 addr, u8 value, u8 eval, u8 mask)
  40 +{
  41 + u32 reg = 0xc40000 + (addr & ~3);
  42 + int shift = (addr & 3) * 8;
  43 + u32 x = cx18_read_reg(cx, reg);
  44 +
  45 + x = (x & ~((u32)0xff << shift)) | ((u32)value << shift);
  46 + cx18_write_reg_expect(cx, x, reg,
  47 + ((u32)eval << shift), ((u32)mask << shift));
  48 + return 0;
  49 +}
  50 +
39 51 int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
40 52 {
41 53 cx18_write_reg(cx, value, 0xc40000 + addr);
42 54 return 0;
43 55 }
44 56  
  57 +int
  58 +cx18_av_write4_expect(struct cx18 *cx, u16 addr, u32 value, u32 eval, u32 mask)
  59 +{
  60 + cx18_write_reg_expect(cx, value, 0xc40000 + addr, eval, mask);
  61 + return 0;
  62 +}
  63 +
45 64 int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value)
46 65 {
47 66 cx18_write_reg_noretry(cx, value, 0xc40000 + addr);
48 67  
49 68  
... ... @@ -98,14 +117,16 @@
98 117  
99 118 cx18_av_loadfw(cx);
100 119 /* Stop 8051 code execution */
101   - cx18_av_write4(cx, CXADEC_DL_CTL, 0x03000000);
  120 + cx18_av_write4_expect(cx, CXADEC_DL_CTL, 0x03000000,
  121 + 0x03000000, 0x13000000);
102 122  
103 123 /* initallize the PLL by toggling sleep bit */
104 124 v = cx18_av_read4(cx, CXADEC_HOST_REG1);
105   - /* enable sleep mode */
106   - cx18_av_write4(cx, CXADEC_HOST_REG1, v | 1);
  125 + /* enable sleep mode - register appears to be read only... */
  126 + cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v | 1, v, 0xfffe);
107 127 /* disable sleep mode */
108   - cx18_av_write4(cx, CXADEC_HOST_REG1, v & 0xfffe);
  128 + cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v & 0xfffe,
  129 + v & 0xfffe, 0xffff);
109 130  
110 131 /* initialize DLLs */
111 132 v = cx18_av_read4(cx, CXADEC_DLL1_DIAG_CTRL) & 0xE1FFFEFF;
112 133  
... ... @@ -125,9 +146,10 @@
125 146  
126 147 v = cx18_av_read4(cx, CXADEC_AFE_DIAG_CTRL3) | 1;
127 148 /* enable TUNE_FIL_RST */
128   - cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v);
  149 + cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3, v, v, 0x03009F0F);
129 150 /* disable TUNE_FIL_RST */
130   - cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v & 0xFFFFFFFE);
  151 + cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3,
  152 + v & 0xFFFFFFFE, v & 0xFFFFFFFE, 0x03009F0F);
131 153  
132 154 /* enable 656 output */
133 155 cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x040C00);
... ... @@ -324,6 +346,7 @@
324 346 {
325 347 struct cx18_av_state *state = &cx->av_state;
326 348 v4l2_std_id std = state->std;
  349 + u8 v;
327 350  
328 351 /* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */
329 352 cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
330 353  
331 354  
332 355  
333 356  
334 357  
335 358  
... ... @@ -333,31 +356,34 @@
333 356 if (std & V4L2_STD_525_60) {
334 357 if (std == V4L2_STD_NTSC_M_JP) {
335 358 /* Japan uses EIAJ audio standard */
336   - cx18_av_write(cx, 0x808, 0xf7);
337   - cx18_av_write(cx, 0x80b, 0x02);
  359 + cx18_av_write_expect(cx, 0x808, 0xf7, 0xf7, 0xff);
  360 + cx18_av_write_expect(cx, 0x80b, 0x02, 0x02, 0x3f);
338 361 } else if (std == V4L2_STD_NTSC_M_KR) {
339 362 /* South Korea uses A2 audio standard */
340   - cx18_av_write(cx, 0x808, 0xf8);
341   - cx18_av_write(cx, 0x80b, 0x03);
  363 + cx18_av_write_expect(cx, 0x808, 0xf8, 0xf8, 0xff);
  364 + cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
342 365 } else {
343 366 /* Others use the BTSC audio standard */
344   - cx18_av_write(cx, 0x808, 0xf6);
345   - cx18_av_write(cx, 0x80b, 0x01);
  367 + cx18_av_write_expect(cx, 0x808, 0xf6, 0xf6, 0xff);
  368 + cx18_av_write_expect(cx, 0x80b, 0x01, 0x01, 0x3f);
346 369 }
347 370 } else if (std & V4L2_STD_PAL) {
348 371 /* Follow tuner change procedure for PAL */
349   - cx18_av_write(cx, 0x808, 0xff);
350   - cx18_av_write(cx, 0x80b, 0x03);
  372 + cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
  373 + cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
351 374 } else if (std & V4L2_STD_SECAM) {
352 375 /* Select autodetect for SECAM */
353   - cx18_av_write(cx, 0x808, 0xff);
354   - cx18_av_write(cx, 0x80b, 0x03);
  376 + cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
  377 + cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
355 378 }
356 379  
357   - if (cx18_av_read(cx, 0x803) & 0x10) {
  380 + v = cx18_av_read(cx, 0x803);
  381 + if (v & 0x10) {
358 382 /* restart audio decoder microcontroller */
359   - cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
360   - cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
  383 + v &= ~0x10;
  384 + cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
  385 + v |= 0x10;
  386 + cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
361 387 }
362 388 }
363 389  
... ... @@ -368,6 +394,7 @@
368 394 u8 is_composite = (vid_input >= CX18_AV_COMPOSITE1 &&
369 395 vid_input <= CX18_AV_COMPOSITE8);
370 396 u8 reg;
  397 + u8 v;
371 398  
372 399 CX18_DEBUG_INFO("decoder set video input %d, audio input %d\n",
373 400 vid_input, aud_input);
374 401  
375 402  
376 403  
377 404  
... ... @@ -413,16 +440,23 @@
413 440 return -EINVAL;
414 441 }
415 442  
416   - cx18_av_write(cx, 0x103, reg);
  443 + cx18_av_write_expect(cx, 0x103, reg, reg, 0xf7);
417 444 /* Set INPUT_MODE to Composite (0) or S-Video (1) */
418 445 cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02);
  446 +
419 447 /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
420   - cx18_av_and_or(cx, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
  448 + v = cx18_av_read(cx, 0x102);
  449 + if (reg & 0x80)
  450 + v &= ~0x2;
  451 + else
  452 + v |= 0x2;
421 453 /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
422 454 if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
423   - cx18_av_and_or(cx, 0x102, ~0x4, 4);
  455 + v |= 0x4;
424 456 else
425   - cx18_av_and_or(cx, 0x102, ~0x4, 0);
  457 + v &= ~0x4;
  458 + cx18_av_write_expect(cx, 0x102, v, v, 0x17);
  459 +
426 460 /*cx18_av_and_or4(cx, 0x104, ~0x001b4180, 0x00004180);*/
427 461  
428 462 state->vid_input = vid_input;
429 463  
430 464  
431 465  
432 466  
433 467  
434 468  
435 469  
... ... @@ -799,40 +833,47 @@
799 833 }
800 834  
801 835 case VIDIOC_S_TUNER:
  836 + {
  837 + u8 v;
  838 +
802 839 if (state->radio)
803 840 break;
804 841  
  842 + v = cx18_av_read(cx, 0x809);
  843 + v &= ~0xf;
  844 +
805 845 switch (vt->audmode) {
806 846 case V4L2_TUNER_MODE_MONO:
807 847 /* mono -> mono
808 848 stereo -> mono
809 849 bilingual -> lang1 */
810   - cx18_av_and_or(cx, 0x809, ~0xf, 0x00);
811 850 break;
812 851 case V4L2_TUNER_MODE_STEREO:
813 852 case V4L2_TUNER_MODE_LANG1:
814 853 /* mono -> mono
815 854 stereo -> stereo
816 855 bilingual -> lang1 */
817   - cx18_av_and_or(cx, 0x809, ~0xf, 0x04);
  856 + v |= 0x4;
818 857 break;
819 858 case V4L2_TUNER_MODE_LANG1_LANG2:
820 859 /* mono -> mono
821 860 stereo -> stereo
822 861 bilingual -> lang1/lang2 */
823   - cx18_av_and_or(cx, 0x809, ~0xf, 0x07);
  862 + v |= 0x7;
824 863 break;
825 864 case V4L2_TUNER_MODE_LANG2:
826 865 /* mono -> mono
827 866 stereo -> stereo
828 867 bilingual -> lang2 */
829   - cx18_av_and_or(cx, 0x809, ~0xf, 0x01);
  868 + v |= 0x1;
830 869 break;
831 870 default:
832 871 return -EINVAL;
833 872 }
  873 + cx18_av_write_expect(cx, 0x809, v, v, 0xff);
834 874 state->audmode = vt->audmode;
835 875 break;
  876 + }
836 877  
837 878 case VIDIOC_G_FMT:
838 879 return get_v4lfmt(cx, (struct v4l2_format *)arg);
drivers/media/video/cx18/cx18-av-core.h
... ... @@ -302,6 +302,9 @@
302 302 int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
303 303 int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
304 304 int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value);
  305 +int cx18_av_write_expect(struct cx18 *cx, u16 addr, u8 value, u8 eval, u8 mask);
  306 +int cx18_av_write4_expect(struct cx18 *cx, u16 addr, u32 value, u32 eval,
  307 + u32 mask);
305 308 u8 cx18_av_read(struct cx18 *cx, u16 addr);
306 309 u32 cx18_av_read4(struct cx18 *cx, u16 addr);
307 310 u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr);
drivers/media/video/cx18/cx18-av-firmware.c
... ... @@ -43,11 +43,13 @@
43 43 /* The firmware load often has byte errors, so allow for several
44 44 retries, both at byte level and at the firmware load level. */
45 45 while (retries1 < 5) {
46   - cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
47   - cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6);
  46 + cx18_av_write4_expect(cx, CXADEC_CHIP_CTRL, 0x00010000,
  47 + 0x00008430, 0xffffffff); /* cx25843 */
  48 + cx18_av_write_expect(cx, CXADEC_STD_DET_CTL, 0xf6, 0xf6, 0xff);
48 49  
49   - /* Reset the Mako core (Register is undocumented.) */
50   - cx18_av_write4(cx, 0x8100, 0x00010000);
  50 + /* Reset the Mako core, Register is alias of CXADEC_CHIP_CTRL */
  51 + cx18_av_write4_expect(cx, 0x8100, 0x00010000,
  52 + 0x00008430, 0xffffffff); /* cx25843 */
51 53  
52 54 /* Put the 8051 in reset and enable firmware upload */
53 55 cx18_av_write4_noretry(cx, CXADEC_DL_CTL, 0x0F000000);
... ... @@ -93,7 +95,8 @@
93 95 return -EIO;
94 96 }
95 97  
96   - cx18_av_write4(cx, CXADEC_DL_CTL, 0x13000000 | fw->size);
  98 + cx18_av_write4_expect(cx, CXADEC_DL_CTL,
  99 + 0x13000000 | fw->size, 0x13000000, 0x13000000);
97 100  
98 101 /* Output to the 416 */
99 102 cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x78000);
... ... @@ -118,7 +121,8 @@
118 121 passthrough */
119 122 cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5000B687);
120 123  
121   - cx18_av_write4(cx, CXADEC_STD_DET_CTL, 0x000000F6);
  124 + cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, 0x000000F6, 0x000000F6,
  125 + 0x3F00FFFF);
122 126 /* CxDevWrReg(CXADEC_STD_DET_CTL, 0x000000FF); */
123 127  
124 128 /* Set bit 0 in register 0x9CC to signify that this is MiniMe. */
... ... @@ -136,7 +140,7 @@
136 140 v |= 0xFF; /* Auto by default */
137 141 v |= 0x400; /* Stereo by default */
138 142 v |= 0x14000000;
139   - cx18_av_write4(cx, CXADEC_STD_DET_CTL, v);
  143 + cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF);
140 144  
141 145 release_firmware(fw);
142 146  
drivers/media/video/cx18/cx18-firmware.c
... ... @@ -200,8 +200,10 @@
200 200 void cx18_halt_firmware(struct cx18 *cx)
201 201 {
202 202 CX18_DEBUG_INFO("Preparing for firmware halt.\n");
203   - cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
204   - cx18_write_reg(cx, 0x00020002, CX18_ADEC_CONTROL);
  203 + cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
  204 + 0x0000000F, 0x000F000F);
  205 + cx18_write_reg_expect(cx, 0x00020002, CX18_ADEC_CONTROL,
  206 + 0x00000002, 0x00020002);
205 207 }
206 208  
207 209 void cx18_init_power(struct cx18 *cx, int lowpwr)
... ... @@ -211,7 +213,8 @@
211 213 cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN);
212 214  
213 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 219 /* The fast clock is at 200/245 MHz */
217 220 cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
218 221  
219 222  
... ... @@ -248,22 +251,34 @@
248 251 /* VFC = disabled */
249 252 /* USB = disabled */
250 253  
251   - cx18_write_reg(cx, lowpwr ? 0xFFFF0020 : 0x00060004,
252   - CX18_CLOCK_SELECT1);
253   - cx18_write_reg(cx, lowpwr ? 0xFFFF0004 : 0x00060006,
254   - CX18_CLOCK_SELECT2);
  254 + if (lowpwr) {
  255 + cx18_write_reg_expect(cx, 0xFFFF0020, CX18_CLOCK_SELECT1,
  256 + 0x00000020, 0xFFFFFFFF);
  257 + cx18_write_reg_expect(cx, 0xFFFF0004, CX18_CLOCK_SELECT2,
  258 + 0x00000004, 0xFFFFFFFF);
  259 + } else {
  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 + }
255 266  
256   - cx18_write_reg(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1);
257   - cx18_write_reg(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2);
258   -
259   - cx18_write_reg(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1);
260   - cx18_write_reg(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2);
  267 + cx18_write_reg_expect(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1,
  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 277 void cx18_init_memory(struct cx18 *cx)
264 278 {
265 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 282 cx18_msleep_timeout(10, 0);
268 283  
269 284 cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
270 285  
... ... @@ -282,13 +297,15 @@
282 297  
283 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 302 cx18_msleep_timeout(10, 0);
287 303  
288 304 /* use power-down mode when idle */
289 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 310 cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7);
294 311 cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR);
... ... @@ -310,7 +327,9 @@
310 327 /* Allow chip to control CLKRUN */
311 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 334 cx18_msleep_timeout(1, 0);
316 335  
... ... @@ -325,7 +344,8 @@
325 344 cx18_write_enc(cx, 0xE51FF004, 0);
326 345 cx18_write_enc(cx, 0xa00000, 4); /* todo: not hardcoded */
327 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 349 cx18_msleep_timeout(500, 0);
330 350  
331 351 sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
... ... @@ -335,7 +355,9 @@
335 355 int retries = 0;
336 356  
337 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 361 while (retries++ < 50) { /* Loop for max 500mS */
340 362 if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET)
341 363 & 1) == 0)
... ... @@ -352,7 +374,7 @@
352 374 return -EIO;
353 375 }
354 376 /* initialize GPIO */
355   - cx18_write_reg(cx, 0x14001400, 0xC78110);
  377 + cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400);
356 378 return 0;
357 379 }
drivers/media/video/cx18/cx18-gpio.c
... ... @@ -47,15 +47,21 @@
47 47  
48 48 static void gpio_write(struct cx18 *cx)
49 49 {
50   - u32 dir = cx->gpio_dir;
51   - u32 val = cx->gpio_val;
  50 + u32 dir_lo = cx->gpio_dir & 0xffff;
  51 + u32 val_lo = cx->gpio_val & 0xffff;
  52 + u32 dir_hi = cx->gpio_dir >> 16;
  53 + u32 val_hi = cx->gpio_val >> 16;
52 54  
53   - cx18_write_reg(cx, (dir & 0xffff) << 16, CX18_REG_GPIO_DIR1);
54   - cx18_write_reg(cx, ((dir & 0xffff) << 16) | (val & 0xffff),
55   - CX18_REG_GPIO_OUT1);
56   - cx18_write_reg(cx, dir & 0xffff0000, CX18_REG_GPIO_DIR2);
57   - cx18_write_reg_sync(cx, (dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
58   - CX18_REG_GPIO_OUT2);
  55 + cx18_write_reg_expect(cx, dir_lo << 16,
  56 + CX18_REG_GPIO_DIR1, ~dir_lo, dir_lo);
  57 + cx18_write_reg_expect(cx, (dir_lo << 16) | val_lo,
  58 + CX18_REG_GPIO_OUT1, val_lo, dir_lo);
  59 + cx18_write_reg_expect(cx, dir_hi << 16,
  60 + CX18_REG_GPIO_DIR2, ~dir_hi, dir_hi);
  61 + cx18_write_reg_expect(cx, (dir_hi << 16) | val_hi,
  62 + CX18_REG_GPIO_OUT2, val_hi, dir_hi);
  63 + if (!cx18_retry_mmio)
  64 + (void) cx18_read_reg(cx, CX18_REG_GPIO_OUT2); /* sync */
59 65 }
60 66  
61 67 void cx18_reset_i2c_slaves_gpio(struct cx18 *cx)
drivers/media/video/cx18/cx18-i2c.c
... ... @@ -27,6 +27,7 @@
27 27 #include "cx18-gpio.h"
28 28 #include "cx18-av-core.h"
29 29 #include "cx18-i2c.h"
  30 +#include "cx18-irq.h"
30 31  
31 32 #define CX18_REG_I2C_1_WR 0xf15000
32 33 #define CX18_REG_I2C_1_RD 0xf15008
33 34  
34 35  
35 36  
36 37  
37 38  
38 39  
... ... @@ -396,22 +397,31 @@
396 397 if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) {
397 398 /* Reset/Unreset I2C hardware block */
398 399 /* Clock select 220MHz */
399   - cx18_write_reg(cx, 0x10000000, 0xc71004);
  400 + cx18_write_reg_expect(cx, 0x10000000, 0xc71004,
  401 + 0x00000000, 0x10001000);
400 402 /* Clock Enable */
401   - cx18_write_reg_sync(cx, 0x10001000, 0xc71024);
  403 + cx18_write_reg_expect(cx, 0x10001000, 0xc71024,
  404 + 0x00001000, 0x10001000);
402 405 }
403 406 /* courtesy of Steven Toth <stoth@hauppauge.com> */
404   - cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c);
  407 + cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);
  408 + if (!cx18_retry_mmio)
  409 + (void) cx18_read_reg(cx, 0xc7001c); /* sync */
405 410 mdelay(10);
406   - cx18_write_reg_sync(cx, 0x00c000c0, 0xc7001c);
  411 + cx18_write_reg_expect(cx, 0x00c000c0, 0xc7001c, 0x000000c0, 0x00c000c0);
  412 + if (!cx18_retry_mmio)
  413 + (void) cx18_read_reg(cx, 0xc7001c); /* sync */
407 414 mdelay(10);
408   - cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c);
  415 + cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);
  416 + if (!cx18_retry_mmio)
  417 + (void) cx18_read_reg(cx, 0xc7001c); /* sync */
409 418 mdelay(10);
410 419  
411 420 /* Set to edge-triggered intrs. */
412   - cx18_write_reg_sync(cx, 0x00c00000, 0xc730c8);
  421 + cx18_write_reg(cx, 0x00c00000, 0xc730c8);
413 422 /* Clear any stale intrs */
414   - cx18_write_reg_sync(cx, 0x00c00000, 0xc730c4);
  423 + cx18_write_reg_expect(cx, HW2_I2C1_INT|HW2_I2C2_INT, HW2_INT_CLR_STATUS,
  424 + ~(HW2_I2C1_INT|HW2_I2C2_INT), HW2_I2C1_INT|HW2_I2C2_INT);
415 425  
416 426 /* Hw I2C1 Clock Freq ~100kHz */
417 427 cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR);