diff options
Diffstat (limited to 'drivers/media/video/cx25840/cx25840-audio.c')
-rw-r--r-- | drivers/media/video/cx25840/cx25840-audio.c | 53 |
1 files changed, 32 insertions, 21 deletions
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index f897c1ebd5f..f93b5160bb4 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); } } |