Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=87410dab1238623e082e9a78a62f1bbeb6c475e3
Commit:     87410dab1238623e082e9a78a62f1bbeb6c475e3
Parent:     372978055dd564d97ca1b4099c99296eaff1fe19
Author:     Hans Verkuil <[EMAIL PROTECTED]>
AuthorDate: Sun Aug 5 08:00:36 2007 -0300
Committer:  Mauro Carvalho Chehab <[EMAIL PROTECTED]>
CommitDate: Tue Oct 9 22:04:55 2007 -0300

    V4L/DVB (5997): cx25840: fix audio mute handling and reporting
    
    Audio muting for the tuner input was implemented by stopping the
    audio microcontroller and restarting it on unmute. However, it
    appears that this method can actually crash the audio firmware.
    It's rare and seems to happen with NTSC only.
    
    It has been reimplemented by setting to volume to 0. In addition, the
    reporting of the mute state has been improved as well: it used to be
    impossible to detect whether the audio was muted by the user or if it
    was muted due to the microcontroller trying to detect the audio
    standard. This is now clearly stated.
    
    Signed-off-by: Hans Verkuil <[EMAIL PROTECTED]>
    Signed-off-by: Mauro Carvalho Chehab <[EMAIL PROTECTED]>
---
 drivers/media/video/cx25840/cx25840-audio.c |   53 ++++++++++++++++-----------
 drivers/media/video/cx25840/cx25840-core.c  |    6 ++-
 drivers/media/video/cx25840/cx25840-core.h  |    1 +
 3 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/drivers/media/video/cx25840/cx25840-audio.c 
b/drivers/media/video/cx25840/cx25840-audio.c
index f897c1e..f93b516 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -194,19 +194,34 @@ void cx25840_audio_set_path(struct i2c_client *client)
 
 static int get_volume(struct i2c_client *client)
 {
+       struct cx25840_state *state = i2c_get_clientdata(client);
+       int vol;
+
+       if (state->unmute_volume >= 0)
+               return state->unmute_volume;
+
        /* Volume runs +18dB to -96dB in 1/2dB steps
         * change to fit the msp3400 -114dB to +12dB range */
 
        /* check PATH1_VOLUME */
-       int vol = 228 - cx25840_read(client, 0x8d4);
+       vol = 228 - cx25840_read(client, 0x8d4);
        vol = (vol / 2) + 23;
        return vol << 9;
 }
 
 static void set_volume(struct i2c_client *client, int volume)
 {
-       /* First convert the volume to msp3400 values (0-127) */
-       int vol = volume >> 9;
+       struct cx25840_state *state = i2c_get_clientdata(client);
+       int vol;
+
+       if (state->unmute_volume >= 0) {
+               state->unmute_volume = volume;
+               return;
+       }
+
+       /* Convert the volume to msp3400 values (0-127) */
+       vol = volume >> 9;
+
        /* now scale it up to cx25840 values
         * -114dB to -96dB maps to 0
         * this should be 19, but in my testing that was 4dB too loud */
@@ -284,30 +299,26 @@ static void set_balance(struct i2c_client *client, int 
balance)
 
 static int get_mute(struct i2c_client *client)
 {
-       /* check SRC1_MUTE_EN */
-       return cx25840_read(client, 0x8d3) & 0x2 ? 1 : 0;
+       struct cx25840_state *state = i2c_get_clientdata(client);
+
+       return state->unmute_volume >= 0;
 }
 
 static void set_mute(struct i2c_client *client, int mute)
 {
        struct cx25840_state *state = i2c_get_clientdata(client);
 
-       if (state->aud_input != CX25840_AUDIO_SERIAL) {
-               /* 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. */
-               if (mute) {
-                       /* disable microcontroller */
-                       cx25840_and_or(client, 0x803, ~0x10, 0x00);
-                       cx25840_write(client, 0x8d3, 0x1f);
-               } else {
-                       /* enable microcontroller */
-                       cx25840_and_or(client, 0x803, ~0x10, 0x10);
-               }
-       } else {
-               /* SRC1_MUTE_EN */
-               cx25840_and_or(client, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
+       if (mute && state->unmute_volume == -1) {
+               int vol = get_volume(client);
+
+               set_volume(client, 0);
+               state->unmute_volume = vol;
+       }
+       else if (!mute && state->unmute_volume != -1) {
+               int vol = state->unmute_volume;
+
+               state->unmute_volume = -1;
+               set_volume(client, vol);
        }
 }
 
diff --git a/drivers/media/video/cx25840/cx25840-core.c 
b/drivers/media/video/cx25840/cx25840-core.c
index 9f99007..65ad794 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -915,6 +915,7 @@ static int cx25840_detect_client(struct i2c_adapter 
*adapter, int address,
        state->audclk_freq = 48000;
        state->pvr150_workaround = 0;
        state->audmode = V4L2_TUNER_MODE_LANG1;
+       state->unmute_volume = -1;
        state->vbi_line_offset = 8;
        state->id = id;
        state->rev = device_id;
@@ -1066,9 +1067,10 @@ static void log_audio_status(struct i2c_client *client)
        }
        v4l_info(client, "Detected audio standard:   %s\n", p);
        v4l_info(client, "Audio muted:               %s\n",
-                   (mute_ctl & 0x2) ? "yes" : "no");
+                   (state->unmute_volume >= 0) ? "yes" : "no");
        v4l_info(client, "Audio microcontroller:     %s\n",
-                   (download_ctl & 0x10) ? "running" : "stopped");
+                   (download_ctl & 0x10) ?
+                               ((mute_ctl & 0x2) ? "detecting" : "running") : 
"stopped");
 
        switch (audio_config >> 4) {
        case 0x00: p = "undefined"; break;
diff --git a/drivers/media/video/cx25840/cx25840-core.h 
b/drivers/media/video/cx25840/cx25840-core.h
index 8c1fbd9..86e2edf 100644
--- a/drivers/media/video/cx25840/cx25840-core.h
+++ b/drivers/media/video/cx25840/cx25840-core.h
@@ -42,6 +42,7 @@ struct cx25840_state {
        enum cx25840_audio_input aud_input;
        u32 audclk_freq;
        int audmode;
+       int unmute_volume; /* -1 if not muted */
        int vbi_line_offset;
        u32 id;
        u32 rev;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to