aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx25840/cx25840-audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx25840/cx25840-audio.c')
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c53
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 f897c1ebd5f3..f93b5160bb4f 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)
194 194
195static int get_volume(struct i2c_client *client) 195static int get_volume(struct i2c_client *client)
196{ 196{
197 struct cx25840_state *state = i2c_get_clientdata(client);
198 int vol;
199
200 if (state->unmute_volume >= 0)
201 return state->unmute_volume;
202
197 /* Volume runs +18dB to -96dB in 1/2dB steps 203 /* Volume runs +18dB to -96dB in 1/2dB steps
198 * change to fit the msp3400 -114dB to +12dB range */ 204 * change to fit the msp3400 -114dB to +12dB range */
199 205
200 /* check PATH1_VOLUME */ 206 /* check PATH1_VOLUME */
201 int vol = 228 - cx25840_read(client, 0x8d4); 207 vol = 228 - cx25840_read(client, 0x8d4);
202 vol = (vol / 2) + 23; 208 vol = (vol / 2) + 23;
203 return vol << 9; 209 return vol << 9;
204} 210}
205 211
206static void set_volume(struct i2c_client *client, int volume) 212static void set_volume(struct i2c_client *client, int volume)
207{ 213{
208 /* First convert the volume to msp3400 values (0-127) */ 214 struct cx25840_state *state = i2c_get_clientdata(client);
209 int vol = volume >> 9; 215 int vol;
216
217 if (state->unmute_volume >= 0) {
218 state->unmute_volume = volume;
219 return;
220 }
221
222 /* Convert the volume to msp3400 values (0-127) */
223 vol = volume >> 9;
224
210 /* now scale it up to cx25840 values 225 /* now scale it up to cx25840 values
211 * -114dB to -96dB maps to 0 226 * -114dB to -96dB maps to 0
212 * this should be 19, but in my testing that was 4dB too loud */ 227 * 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)
284 299
285static int get_mute(struct i2c_client *client) 300static int get_mute(struct i2c_client *client)
286{ 301{
287 /* check SRC1_MUTE_EN */ 302 struct cx25840_state *state = i2c_get_clientdata(client);
288 return cx25840_read(client, 0x8d3) & 0x2 ? 1 : 0; 303
304 return state->unmute_volume >= 0;
289} 305}
290 306
291static void set_mute(struct i2c_client *client, int mute) 307static void set_mute(struct i2c_client *client, int mute)
292{ 308{
293 struct cx25840_state *state = i2c_get_clientdata(client); 309 struct cx25840_state *state = i2c_get_clientdata(client);
294 310
295 if (state->aud_input != CX25840_AUDIO_SERIAL) { 311 if (mute && state->unmute_volume == -1) {
296 /* Must turn off microcontroller in order to mute sound. 312 int vol = get_volume(client);
297 * Not sure if this is the best method, but it does work. 313
298 * If the microcontroller is running, then it will undo any 314 set_volume(client, 0);
299 * changes to the mute register. */ 315 state->unmute_volume = vol;
300 if (mute) { 316 }
301 /* disable microcontroller */ 317 else if (!mute && state->unmute_volume != -1) {
302 cx25840_and_or(client, 0x803, ~0x10, 0x00); 318 int vol = state->unmute_volume;
303 cx25840_write(client, 0x8d3, 0x1f); 319
304 } else { 320 state->unmute_volume = -1;
305 /* enable microcontroller */ 321 set_volume(client, vol);
306 cx25840_and_or(client, 0x803, ~0x10, 0x10);
307 }
308 } else {
309 /* SRC1_MUTE_EN */
310 cx25840_and_or(client, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
311 } 322 }
312} 323}
313 324