aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx25840
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx25840')
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c53
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c6
-rw-r--r--drivers/media/video/cx25840/cx25840-core.h1
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
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
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;