Skip to content

Commit d312a46

Browse files
hverkuilMauro Carvalho Chehab
authored andcommitted
V4L/DVB (3324): msp3400 audio handling bug fixes.
- Check capabilities for audio settings (volume, balance, bass, treble, loudness, mute) - added loudness support - added missing VIDEO_AUDIO_BALANCE flags for v4l1 compatibility - do not call msp_any_detect_stereo for non-autoselect chips to retrieve the current stereo setting: that will temporarily mute the sound. It is only needed when the stereo mode might be changed, and for autoselect msp processors that do not periodically need to update their stereo setting. - do not wake up the thread if the standard did not change. Prevents temporary audio drop-out if the standard is set to the same value. - fix confused stereo detect code where V4L2_TUNER_SUB_STEREO and V4L2_TUNER_MODE_STEREO values were used incorrectly. - stereo mode reporting was broken (v4l2 value used to index a string array expecting v4l1 mode values). - do not set dsp register 0x30 in the 3410d thread: that register does not exist for pre-'G' revision msp chips. Signed-off-by: Hans Verkuil <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent 1157020 commit d312a46

File tree

3 files changed

+156
-80
lines changed

3 files changed

+156
-80
lines changed

drivers/media/video/msp3400-driver.c

Lines changed: 138 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -283,33 +283,57 @@ void msp_set_scart(struct i2c_client *client, int in, int out)
283283

284284
void msp_set_mute(struct i2c_client *client)
285285
{
286+
struct msp_state *state = i2c_get_clientdata(client);
287+
286288
v4l_dbg(1, client, "mute audio\n");
287-
msp_write_dsp(client, 0x0000, 0); /* loudspeaker */
288-
msp_write_dsp(client, 0x0006, 0); /* headphones */
289+
msp_write_dsp(client, 0x0000, 0);
290+
msp_write_dsp(client, 0x0007, 1);
291+
if (state->has_scart2_out_volume)
292+
msp_write_dsp(client, 0x0040, 1);
293+
if (state->has_headphones)
294+
msp_write_dsp(client, 0x0006, 0);
289295
}
290296

291297
void msp_set_audio(struct i2c_client *client)
292298
{
293299
struct msp_state *state = i2c_get_clientdata(client);
294-
int val = 0, bal = 0, bass, treble;
300+
int bal = 0, bass, treble, loudness;
301+
int val = 0;
295302

296303
if (!state->muted)
297304
val = (state->volume * 0x7f / 65535) << 8;
305+
306+
v4l_dbg(1, client, "mute=%s volume=%d\n",
307+
state->muted ? "on" : "off", state->volume);
308+
309+
msp_write_dsp(client, 0x0000, val);
310+
msp_write_dsp(client, 0x0007, state->muted ? 0x1 : (val | 0x1));
311+
if (state->has_scart2_out_volume)
312+
msp_write_dsp(client, 0x0040, state->muted ? 0x1 : (val | 0x1));
313+
if (state->has_headphones)
314+
msp_write_dsp(client, 0x0006, val);
315+
if (!state->has_sound_processing)
316+
return;
317+
298318
if (val)
299-
bal = (state->balance / 256) - 128;
319+
bal = (u8)((state->balance / 256) - 128);
300320
bass = ((state->bass - 32768) * 0x60 / 65535) << 8;
301321
treble = ((state->treble - 32768) * 0x60 / 65535) << 8;
322+
loudness = state->loudness ? ((5 * 4) << 8) : 0;
302323

303-
v4l_dbg(1, client, "mute=%s volume=%d balance=%d bass=%d treble=%d\n",
304-
state->muted ? "on" : "off", state->volume, state->balance,
305-
state->bass, state->treble);
324+
v4l_dbg(1, client, "balance=%d bass=%d treble=%d loudness=%d\n",
325+
state->balance, state->bass, state->treble, state->loudness);
306326

307-
msp_write_dsp(client, 0x0000, val); /* loudspeaker */
308-
msp_write_dsp(client, 0x0006, val); /* headphones */
309-
msp_write_dsp(client, 0x0007, state->muted ? 0x1 : (val | 0x1));
310327
msp_write_dsp(client, 0x0001, bal << 8);
311-
msp_write_dsp(client, 0x0002, bass); /* loudspeaker */
312-
msp_write_dsp(client, 0x0003, treble); /* loudspeaker */
328+
msp_write_dsp(client, 0x0002, bass);
329+
msp_write_dsp(client, 0x0003, treble);
330+
msp_write_dsp(client, 0x0004, loudness);
331+
if (!state->has_headphones)
332+
return;
333+
msp_write_dsp(client, 0x0030, bal << 8);
334+
msp_write_dsp(client, 0x0031, bass);
335+
msp_write_dsp(client, 0x0032, treble);
336+
msp_write_dsp(client, 0x0033, loudness);
313337
}
314338

315339
int msp_modus(struct i2c_client *client)
@@ -421,7 +445,7 @@ static void msp_any_detect_stereo(struct i2c_client *client)
421445
}
422446
}
423447

424-
static struct v4l2_queryctrl msp_qctrl[] = {
448+
static struct v4l2_queryctrl msp_qctrl_std[] = {
425449
{
426450
.id = V4L2_CID_AUDIO_VOLUME,
427451
.name = "Volume",
@@ -431,15 +455,6 @@ static struct v4l2_queryctrl msp_qctrl[] = {
431455
.default_value = 58880,
432456
.flags = 0,
433457
.type = V4L2_CTRL_TYPE_INTEGER,
434-
},{
435-
.id = V4L2_CID_AUDIO_BALANCE,
436-
.name = "Balance",
437-
.minimum = 0,
438-
.maximum = 65535,
439-
.step = 65535/100,
440-
.default_value = 32768,
441-
.flags = 0,
442-
.type = V4L2_CTRL_TYPE_INTEGER,
443458
},{
444459
.id = V4L2_CID_AUDIO_MUTE,
445460
.name = "Mute",
@@ -449,6 +464,19 @@ static struct v4l2_queryctrl msp_qctrl[] = {
449464
.default_value = 1,
450465
.flags = 0,
451466
.type = V4L2_CTRL_TYPE_BOOLEAN,
467+
},
468+
};
469+
470+
static struct v4l2_queryctrl msp_qctrl_sound_processing[] = {
471+
{
472+
.id = V4L2_CID_AUDIO_BALANCE,
473+
.name = "Balance",
474+
.minimum = 0,
475+
.maximum = 65535,
476+
.step = 65535/100,
477+
.default_value = 32768,
478+
.flags = 0,
479+
.type = V4L2_CTRL_TYPE_INTEGER,
452480
},{
453481
.id = V4L2_CID_AUDIO_BASS,
454482
.name = "Bass",
@@ -465,6 +493,15 @@ static struct v4l2_queryctrl msp_qctrl[] = {
465493
.step = 65535/100,
466494
.default_value = 32768,
467495
.type = V4L2_CTRL_TYPE_INTEGER,
496+
},{
497+
.id = V4L2_CID_AUDIO_LOUDNESS,
498+
.name = "Loudness",
499+
.minimum = 0,
500+
.maximum = 1,
501+
.step = 1,
502+
.default_value = 1,
503+
.flags = 0,
504+
.type = V4L2_CTRL_TYPE_BOOLEAN,
468505
},
469506
};
470507

@@ -490,24 +527,36 @@ static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
490527
struct msp_state *state = i2c_get_clientdata(client);
491528

492529
switch (ctrl->id) {
530+
case V4L2_CID_AUDIO_VOLUME:
531+
ctrl->value = state->volume;
532+
break;
533+
493534
case V4L2_CID_AUDIO_MUTE:
494535
ctrl->value = state->muted;
495536
break;
496537

497538
case V4L2_CID_AUDIO_BALANCE:
539+
if (!state->has_sound_processing)
540+
return -EINVAL;
498541
ctrl->value = state->balance;
499542
break;
500543

501544
case V4L2_CID_AUDIO_BASS:
545+
if (!state->has_sound_processing)
546+
return -EINVAL;
502547
ctrl->value = state->bass;
503548
break;
504549

505550
case V4L2_CID_AUDIO_TREBLE:
551+
if (!state->has_sound_processing)
552+
return -EINVAL;
506553
ctrl->value = state->treble;
507554
break;
508555

509-
case V4L2_CID_AUDIO_VOLUME:
510-
ctrl->value = state->volume;
556+
case V4L2_CID_AUDIO_LOUDNESS:
557+
if (!state->has_sound_processing)
558+
return -EINVAL;
559+
ctrl->value = state->loudness;
511560
break;
512561

513562
default:
@@ -521,28 +570,40 @@ static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
521570
struct msp_state *state = i2c_get_clientdata(client);
522571

523572
switch (ctrl->id) {
573+
case V4L2_CID_AUDIO_VOLUME:
574+
state->volume = ctrl->value;
575+
if (state->volume == 0)
576+
state->balance = 32768;
577+
break;
578+
524579
case V4L2_CID_AUDIO_MUTE:
525580
if (ctrl->value < 0 || ctrl->value >= 2)
526581
return -ERANGE;
527582
state->muted = ctrl->value;
528583
break;
529584

530585
case V4L2_CID_AUDIO_BASS:
586+
if (!state->has_sound_processing)
587+
return -EINVAL;
531588
state->bass = ctrl->value;
532589
break;
533590

534591
case V4L2_CID_AUDIO_TREBLE:
592+
if (!state->has_sound_processing)
593+
return -EINVAL;
535594
state->treble = ctrl->value;
536595
break;
537596

538-
case V4L2_CID_AUDIO_BALANCE:
539-
state->balance = ctrl->value;
597+
case V4L2_CID_AUDIO_LOUDNESS:
598+
if (!state->has_sound_processing)
599+
return -EINVAL;
600+
state->loudness = ctrl->value;
540601
break;
541602

542-
case V4L2_CID_AUDIO_VOLUME:
543-
state->volume = ctrl->value;
544-
if (state->volume == 0)
545-
state->balance = 32768;
603+
case V4L2_CID_AUDIO_BALANCE:
604+
if (!state->has_sound_processing)
605+
return -EINVAL;
606+
state->balance = ctrl->value;
546607
break;
547608

548609
default:
@@ -628,21 +689,20 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
628689
{
629690
struct video_audio *va = arg;
630691

631-
va->flags |= VIDEO_AUDIO_VOLUME |
632-
VIDEO_AUDIO_BASS |
633-
VIDEO_AUDIO_TREBLE |
634-
VIDEO_AUDIO_MUTABLE;
635-
if (state->muted)
636-
va->flags |= VIDEO_AUDIO_MUTE;
637-
692+
va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_MUTABLE;
693+
if (state->has_sound_processing)
694+
va->flags |= VIDEO_AUDIO_BALANCE |
695+
VIDEO_AUDIO_BASS |
696+
VIDEO_AUDIO_TREBLE;
638697
if (state->muted)
639698
va->flags |= VIDEO_AUDIO_MUTE;
640699
va->volume = state->volume;
641700
va->balance = state->volume ? state->balance : 32768;
642701
va->bass = state->bass;
643702
va->treble = state->treble;
644703

645-
msp_any_detect_stereo(client);
704+
if (state->opmode == OPMODE_AUTOSELECT)
705+
msp_any_detect_stereo(client);
646706
va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans);
647707
break;
648708
}
@@ -666,15 +726,24 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
666726
case VIDIOCSCHAN:
667727
{
668728
struct video_channel *vc = arg;
729+
int update = 0;
730+
v4l2_std_id std;
669731

732+
if (state->radio)
733+
update = 1;
670734
state->radio = 0;
671735
if (vc->norm == VIDEO_MODE_PAL)
672-
state->std = V4L2_STD_PAL;
736+
std = V4L2_STD_PAL;
673737
else if (vc->norm == VIDEO_MODE_SECAM)
674-
state->std = V4L2_STD_SECAM;
738+
std = V4L2_STD_SECAM;
675739
else
676-
state->std = V4L2_STD_NTSC;
677-
msp_wake_thread(client);
740+
std = V4L2_STD_NTSC;
741+
if (std != state->std) {
742+
state->std = std;
743+
update = 1;
744+
}
745+
if (update)
746+
msp_wake_thread(client);
678747
break;
679748
}
680749

@@ -699,10 +768,12 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
699768
case VIDIOC_S_STD:
700769
{
701770
v4l2_std_id *id = arg;
771+
int update = state->radio || state->std != *id;
702772

703773
state->std = *id;
704774
state->radio = 0;
705-
msp_wake_thread(client);
775+
if (update)
776+
msp_wake_thread(client);
706777
return 0;
707778
}
708779

@@ -808,7 +879,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
808879
{
809880
struct v4l2_tuner *vt = arg;
810881

811-
msp_any_detect_stereo(client);
882+
if (state->opmode == OPMODE_AUTOSELECT)
883+
msp_any_detect_stereo(client);
812884
vt->audmode = state->audmode;
813885
vt->rxsubchans = state->rxsubchans;
814886
vt->capability = V4L2_TUNER_CAP_STEREO |
@@ -887,9 +959,16 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
887959
struct v4l2_queryctrl *qc = arg;
888960
int i;
889961

890-
for (i = 0; i < ARRAY_SIZE(msp_qctrl); i++)
891-
if (qc->id && qc->id == msp_qctrl[i].id) {
892-
memcpy(qc, &msp_qctrl[i], sizeof(*qc));
962+
for (i = 0; i < ARRAY_SIZE(msp_qctrl_std); i++)
963+
if (qc->id && qc->id == msp_qctrl_std[i].id) {
964+
memcpy(qc, &msp_qctrl_std[i], sizeof(*qc));
965+
return 0;
966+
}
967+
if (!state->has_sound_processing)
968+
return -EINVAL;
969+
for (i = 0; i < ARRAY_SIZE(msp_qctrl_sound_processing); i++)
970+
if (qc->id && qc->id == msp_qctrl_sound_processing[i].id) {
971+
memcpy(qc, &msp_qctrl_sound_processing[i], sizeof(*qc));
893972
return 0;
894973
}
895974
return -EINVAL;
@@ -902,13 +981,17 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
902981
return msp_set_ctrl(client, arg);
903982

904983
case VIDIOC_LOG_STATUS:
905-
msp_any_detect_stereo(client);
984+
if (state->opmode == OPMODE_AUTOSELECT)
985+
msp_any_detect_stereo(client);
906986
v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n",
907987
client->name, state->rev1, state->rev2);
908-
v4l_info(client, "Audio: volume %d balance %d bass %d treble %d%s\n",
909-
state->volume, state->balance,
910-
state->bass, state->treble,
911-
state->muted ? " (muted)" : "");
988+
v4l_info(client, "Audio: volume %d%s\n",
989+
state->volume, state->muted ? " (muted)" : "");
990+
if (state->has_sound_processing) {
991+
v4l_info(client, "Audio: balance %d bass %d treble %d loudness %s\n",
992+
state->balance, state->bass, state->treble,
993+
state->loudness ? "on" : "off");
994+
}
912995
v4l_info(client, "Mode: %s (%s%s)\n", msp_standard_mode_name(state->mode),
913996
(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
914997
(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
@@ -983,6 +1066,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
9831066
state->balance = 32768; /* 0db gain */
9841067
state->bass = 32768;
9851068
state->treble = 32768;
1069+
state->loudness = 0;
9861070
state->input = -1;
9871071
state->muted = 0;
9881072
state->i2s_mode = 0;
@@ -1023,6 +1107,8 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
10231107
/* Has scart2 and scart3 inputs and scart2 output: not in stripped
10241108
down products of the '3' family */
10251109
state->has_scart23_in_scart2_out = msp_family >= 4 || msp_prod_lo < 5;
1110+
/* Has scart2 a volume control? Not in pre-D revisions. */
1111+
state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart23_in_scart2_out;
10261112
/* Has subwoofer output: not in pre-D revs and not in stripped down products */
10271113
state->has_subwoofer = msp_revision >= 'D' && msp_prod_lo < 5;
10281114
/* Has soundprocessing (bass/treble/balance/loudness/equalizer): not in

0 commit comments

Comments
 (0)