aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-av-audio.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-av-audio.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-av-audio.c')
-rw-r--r--drivers/media/video/cx18/cx18-av-audio.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/video/cx18/cx18-av-audio.c
index 0b55837880a7..486cad0c26e0 100644
--- a/drivers/media/video/cx18/cx18-av-audio.c
+++ b/drivers/media/video/cx18/cx18-av-audio.c
@@ -215,12 +215,15 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
215void cx18_av_audio_set_path(struct cx18 *cx) 215void cx18_av_audio_set_path(struct cx18 *cx)
216{ 216{
217 struct cx18_av_state *state = &cx->av_state; 217 struct cx18_av_state *state = &cx->av_state;
218 u8 v;
218 219
219 /* stop microcontroller */ 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 /* assert soft reset */ 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 /* Mute everything to prevent the PFFT! */ 228 /* Mute everything to prevent the PFFT! */
226 cx18_av_write(cx, 0x8d3, 0x1f); 229 cx18_av_write(cx, 0x8d3, 0x1f);
@@ -240,12 +243,14 @@ void cx18_av_audio_set_path(struct cx18 *cx)
240 set_audclk_freq(cx, state->audclk_freq); 243 set_audclk_freq(cx, state->audclk_freq);
241 244
242 /* deassert soft reset */ 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 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { 249 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
246 /* When the microcontroller detects the 250 /* When the microcontroller detects the
247 * audio format, it will unmute the lines */ 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
@@ -347,19 +352,23 @@ static int get_mute(struct cx18 *cx)
347static void set_mute(struct cx18 *cx, int mute) 352static void set_mute(struct cx18 *cx, int mute)
348{ 353{
349 struct cx18_av_state *state = &cx->av_state; 354 struct cx18_av_state *state = &cx->av_state;
355 u8 v;
350 356
351 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { 357 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
352 /* Must turn off microcontroller in order to mute sound. 358 /* Must turn off microcontroller in order to mute sound.
353 * Not sure if this is the best method, but it does work. 359 * Not sure if this is the best method, but it does work.
354 * If the microcontroller is running, then it will undo any 360 * If the microcontroller is running, then it will undo any
355 * changes to the mute register. */ 361 * changes to the mute register. */
362 v = cx18_av_read(cx, 0x803);
356 if (mute) { 363 if (mute) {
357 /* disable microcontroller */ 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 cx18_av_write(cx, 0x8d3, 0x1f); 367 cx18_av_write(cx, 0x8d3, 0x1f);
360 } else { 368 } else {
361 /* enable microcontroller */ 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 } else { 373 } else {
365 /* SRC1_MUTE_EN */ 374 /* SRC1_MUTE_EN */
@@ -375,16 +384,26 @@ int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)
375 384
376 switch (cmd) { 385 switch (cmd) {
377 case VIDIOC_INT_AUDIO_CLOCK_FREQ: 386 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
387 {
388 u8 v;
378 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { 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 cx18_av_write(cx, 0x8d3, 0x1f); 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 retval = set_audclk_freq(cx, *(u32 *)arg); 397 retval = set_audclk_freq(cx, *(u32 *)arg);
384 cx18_av_and_or(cx, 0x810, ~0x1, 0); 398
385 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) 399 v = cx18_av_read(cx, 0x810) & ~0x1;
386 cx18_av_and_or(cx, 0x803, ~0x10, 0x10); 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 return retval; 405 return retval;
406 }
388 407
389 case VIDIOC_G_CTRL: 408 case VIDIOC_G_CTRL:
390 switch (ctrl->id) { 409 switch (ctrl->id) {