summaryrefslogtreecommitdiff
path: root/linux/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
committerAndy Walls <awalls@radix.net>2008-11-02 08:59:04 -0500
commit8d3c3456efe683debd81b7a17171bbb41019ec61 (patch)
tree760e0483a6f776ea0575ef449a465f749510e7d7 /linux/drivers/media/video/cx18/cx18-av-audio.c
parent20294c5bcf01a436fbdb78a6548ec74dad1afd77 (diff)
downloadmediapointer-dvb-s2-8d3c3456efe683debd81b7a17171bbb41019ec61.tar.gz
mediapointer-dvb-s2-8d3c3456efe683debd81b7a17171bbb41019ec61.tar.bz2
cx18: Fix write retries for registers that always change - part 3.
From: Andy Walls <awalls@radix.net> 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. Priority: normal Signed-off-by: Andy Walls <awalls@radix.net>
Diffstat (limited to 'linux/drivers/media/video/cx18/cx18-av-audio.c')
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-audio.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/linux/drivers/media/video/cx18/cx18-av-audio.c b/linux/drivers/media/video/cx18/cx18-av-audio.c
index 0b5583788..486cad0c2 100644
--- a/linux/drivers/media/video/cx18/cx18-av-audio.c
+++ b/linux/drivers/media/video/cx18/cx18-av-audio.c
@@ -215,12 +215,15 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
void cx18_av_audio_set_path(struct cx18 *cx)
{
struct cx18_av_state *state = &cx->av_state;
+ u8 v;
/* stop microcontroller */
- cx18_av_and_or(cx, 0x803, ~0x10, 0);
+ v = cx18_av_read(cx, 0x803) & ~0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
/* assert soft reset */
- cx18_av_and_or(cx, 0x810, ~0x1, 0x01);
+ v = cx18_av_read(cx, 0x810) | 0x01;
+ cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
/* Mute everything to prevent the PFFT! */
cx18_av_write(cx, 0x8d3, 0x1f);
@@ -240,12 +243,14 @@ void cx18_av_audio_set_path(struct cx18 *cx)
set_audclk_freq(cx, state->audclk_freq);
/* deassert soft reset */
- cx18_av_and_or(cx, 0x810, ~0x1, 0x00);
+ v = cx18_av_read(cx, 0x810) & ~0x01;
+ cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
/* When the microcontroller detects the
* audio format, it will unmute the lines */
- cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+ v = cx18_av_read(cx, 0x803) | 0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
}
}
@@ -347,19 +352,23 @@ static int get_mute(struct cx18 *cx)
static void set_mute(struct cx18 *cx, int mute)
{
struct cx18_av_state *state = &cx->av_state;
+ u8 v;
if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
/* Must turn off microcontroller in order to mute sound.
* Not sure if this is the best method, but it does work.
* If the microcontroller is running, then it will undo any
* changes to the mute register. */
+ v = cx18_av_read(cx, 0x803);
if (mute) {
/* disable microcontroller */
- cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
+ v &= ~0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
cx18_av_write(cx, 0x8d3, 0x1f);
} else {
/* enable microcontroller */
- cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+ v |= 0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
}
} else {
/* SRC1_MUTE_EN */
@@ -375,16 +384,26 @@ int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)
switch (cmd) {
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+ {
+ u8 v;
if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
- cx18_av_and_or(cx, 0x803, ~0x10, 0);
+ v = cx18_av_read(cx, 0x803) & ~0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
cx18_av_write(cx, 0x8d3, 0x1f);
}
- cx18_av_and_or(cx, 0x810, ~0x1, 1);
+ v = cx18_av_read(cx, 0x810) | 0x1;
+ cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
+
retval = set_audclk_freq(cx, *(u32 *)arg);
- cx18_av_and_or(cx, 0x810, ~0x1, 0);
- if (state->aud_input > CX18_AV_AUDIO_SERIAL2)
- cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+
+ v = cx18_av_read(cx, 0x810) & ~0x1;
+ cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
+ if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
+ v = cx18_av_read(cx, 0x803) | 0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+ }
return retval;
+ }
case VIDIOC_G_CTRL:
switch (ctrl->id) {