diff options
Diffstat (limited to 'drivers/media/video/cx25840')
-rw-r--r-- | drivers/media/video/cx25840/cx25840-audio.c | 53 | ||||
-rw-r--r-- | drivers/media/video/cx25840/cx25840-core.c | 6 | ||||
-rw-r--r-- | 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 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) | |||
194 | 194 | ||
195 | static int get_volume(struct i2c_client *client) | 195 | static 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 | ||
206 | static void set_volume(struct i2c_client *client, int volume) | 212 | static 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 | ||
285 | static int get_mute(struct i2c_client *client) | 300 | static 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 | ||
291 | static void set_mute(struct i2c_client *client, int mute) | 307 | static 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 | ||
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 9f99007d389..65ad7943dd9 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, | |||
915 | state->audclk_freq = 48000; | 915 | state->audclk_freq = 48000; |
916 | state->pvr150_workaround = 0; | 916 | state->pvr150_workaround = 0; |
917 | state->audmode = V4L2_TUNER_MODE_LANG1; | 917 | state->audmode = V4L2_TUNER_MODE_LANG1; |
918 | state->unmute_volume = -1; | ||
918 | state->vbi_line_offset = 8; | 919 | state->vbi_line_offset = 8; |
919 | state->id = id; | 920 | state->id = id; |
920 | state->rev = device_id; | 921 | state->rev = device_id; |
@@ -1066,9 +1067,10 @@ static void log_audio_status(struct i2c_client *client) | |||
1066 | } | 1067 | } |
1067 | v4l_info(client, "Detected audio standard: %s\n", p); | 1068 | v4l_info(client, "Detected audio standard: %s\n", p); |
1068 | v4l_info(client, "Audio muted: %s\n", | 1069 | v4l_info(client, "Audio muted: %s\n", |
1069 | (mute_ctl & 0x2) ? "yes" : "no"); | 1070 | (state->unmute_volume >= 0) ? "yes" : "no"); |
1070 | v4l_info(client, "Audio microcontroller: %s\n", | 1071 | v4l_info(client, "Audio microcontroller: %s\n", |
1071 | (download_ctl & 0x10) ? "running" : "stopped"); | 1072 | (download_ctl & 0x10) ? |
1073 | ((mute_ctl & 0x2) ? "detecting" : "running") : "stopped"); | ||
1072 | 1074 | ||
1073 | switch (audio_config >> 4) { | 1075 | switch (audio_config >> 4) { |
1074 | case 0x00: p = "undefined"; break; | 1076 | case 0x00: p = "undefined"; break; |
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h index 8c1fbd9b87c..86e2edfc494 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/video/cx25840/cx25840-core.h | |||
@@ -42,6 +42,7 @@ struct cx25840_state { | |||
42 | enum cx25840_audio_input aud_input; | 42 | enum cx25840_audio_input aud_input; |
43 | u32 audclk_freq; | 43 | u32 audclk_freq; |
44 | int audmode; | 44 | int audmode; |
45 | int unmute_volume; /* -1 if not muted */ | ||
45 | int vbi_line_offset; | 46 | int vbi_line_offset; |
46 | u32 id; | 47 | u32 id; |
47 | u32 rev; | 48 | u32 rev; |