Skip to content

Commit a73d511

Browse files
ikminetttiwai
authored andcommitted
ALSA: hda/ca0132: Add unsol handler for DSP and jack detection
This patch adds the unsolicited response handler for incoming DSP responses and jack detection reporting, and routines for reading the incoming DSP response. Signed-off-by: Ian Minett <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent 825315b commit a73d511

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed

sound/pci/hda/patch_ca0132.c

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,6 +1172,59 @@ static int dspio_write_multiple(struct hda_codec *codec,
11721172
return status;
11731173
}
11741174

1175+
static int dspio_read(struct hda_codec *codec, unsigned int *data)
1176+
{
1177+
int status;
1178+
1179+
status = dspio_send(codec, VENDOR_DSPIO_SCP_POST_READ_DATA, 0);
1180+
if (status == -EIO)
1181+
return status;
1182+
1183+
status = dspio_send(codec, VENDOR_DSPIO_STATUS, 0);
1184+
if (status == -EIO ||
1185+
status == VENDOR_STATUS_DSPIO_SCP_RESPONSE_QUEUE_EMPTY)
1186+
return -EIO;
1187+
1188+
*data = snd_hda_codec_read(codec, WIDGET_DSP_CTRL, 0,
1189+
VENDOR_DSPIO_SCP_READ_DATA, 0);
1190+
1191+
return 0;
1192+
}
1193+
1194+
static int dspio_read_multiple(struct hda_codec *codec, unsigned int *buffer,
1195+
unsigned int *buf_size, unsigned int size_count)
1196+
{
1197+
int status = 0;
1198+
unsigned int size = *buf_size;
1199+
unsigned int count;
1200+
unsigned int skip_count;
1201+
unsigned int dummy;
1202+
1203+
if ((buffer == NULL))
1204+
return -1;
1205+
1206+
count = 0;
1207+
while (count < size && count < size_count) {
1208+
status = dspio_read(codec, buffer++);
1209+
if (status != 0)
1210+
break;
1211+
count++;
1212+
}
1213+
1214+
skip_count = count;
1215+
if (status == 0) {
1216+
while (skip_count < size) {
1217+
status = dspio_read(codec, &dummy);
1218+
if (status != 0)
1219+
break;
1220+
skip_count++;
1221+
}
1222+
}
1223+
*buf_size = count;
1224+
1225+
return status;
1226+
}
1227+
11751228
/*
11761229
* Construct the SCP header using corresponding fields
11771230
*/
@@ -1231,6 +1284,38 @@ struct scp_msg {
12311284
unsigned int data[SCP_MAX_DATA_WORDS];
12321285
};
12331286

1287+
static void dspio_clear_response_queue(struct hda_codec *codec)
1288+
{
1289+
unsigned int dummy = 0;
1290+
int status = -1;
1291+
1292+
/* clear all from the response queue */
1293+
do {
1294+
status = dspio_read(codec, &dummy);
1295+
} while (status == 0);
1296+
}
1297+
1298+
static int dspio_get_response_data(struct hda_codec *codec)
1299+
{
1300+
struct ca0132_spec *spec = codec->spec;
1301+
unsigned int data = 0;
1302+
unsigned int count;
1303+
1304+
if (dspio_read(codec, &data) < 0)
1305+
return -EIO;
1306+
1307+
if ((data & 0x00ffffff) == spec->wait_scp_header) {
1308+
spec->scp_resp_header = data;
1309+
spec->scp_resp_count = data >> 27;
1310+
count = spec->wait_num_data;
1311+
dspio_read_multiple(codec, spec->scp_resp_data,
1312+
&spec->scp_resp_count, count);
1313+
return 0;
1314+
}
1315+
1316+
return -EIO;
1317+
}
1318+
12341319
/*
12351320
* Send SCP message to DSP
12361321
*/
@@ -3743,6 +3828,12 @@ static int ca0132_build_controls(struct hda_codec *codec)
37433828
return 0;
37443829
}
37453830

3831+
static void ca0132_init_unsol(struct hda_codec *codec)
3832+
{
3833+
snd_hda_jack_detect_enable(codec, UNSOL_TAG_HP, UNSOL_TAG_HP);
3834+
snd_hda_jack_detect_enable(codec, UNSOL_TAG_AMIC1, UNSOL_TAG_AMIC1);
3835+
}
3836+
37463837
static void refresh_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir)
37473838
{
37483839
unsigned int caps;
@@ -4152,6 +4243,47 @@ static void ca0132_download_dsp(struct hda_codec *codec)
41524243
ca0132_set_dsp_msr(codec, true);
41534244
}
41544245

4246+
static void ca0132_process_dsp_response(struct hda_codec *codec)
4247+
{
4248+
struct ca0132_spec *spec = codec->spec;
4249+
4250+
snd_printdd(KERN_INFO "ca0132_process_dsp_response\n");
4251+
if (spec->wait_scp) {
4252+
if (dspio_get_response_data(codec) >= 0)
4253+
spec->wait_scp = 0;
4254+
}
4255+
4256+
dspio_clear_response_queue(codec);
4257+
}
4258+
4259+
static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res)
4260+
{
4261+
snd_printdd(KERN_INFO "ca0132_unsol_event: 0x%x\n", res);
4262+
4263+
4264+
if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) {
4265+
ca0132_process_dsp_response(codec);
4266+
} else {
4267+
res = snd_hda_jack_get_action(codec,
4268+
(res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f);
4269+
4270+
snd_printdd(KERN_INFO "snd_hda_jack_get_action: 0x%x\n", res);
4271+
4272+
switch (res) {
4273+
case UNSOL_TAG_HP:
4274+
ca0132_select_out(codec);
4275+
snd_hda_jack_report_sync(codec);
4276+
break;
4277+
case UNSOL_TAG_AMIC1:
4278+
ca0132_select_mic(codec);
4279+
snd_hda_jack_report_sync(codec);
4280+
break;
4281+
default:
4282+
break;
4283+
}
4284+
}
4285+
}
4286+
41554287
static int ca0132_init(struct hda_codec *codec)
41564288
{
41574289
struct ca0132_spec *spec = codec->spec;
@@ -4187,9 +4319,13 @@ static int ca0132_init(struct hda_codec *codec)
41874319
for (i = 0; i < spec->num_init_verbs; i++)
41884320
snd_hda_sequence_write(codec, spec->init_verbs[i]);
41894321

4322+
ca0132_init_unsol(codec);
4323+
41904324
ca0132_select_out(codec);
41914325
ca0132_select_mic(codec);
41924326

4327+
snd_hda_jack_report_sync(codec);
4328+
41934329
snd_hda_power_down(codec);
41944330

41954331
return 0;
@@ -4211,11 +4347,13 @@ static struct hda_codec_ops ca0132_patch_ops = {
42114347
.build_pcms = ca0132_build_pcms,
42124348
.init = ca0132_init,
42134349
.free = ca0132_free,
4350+
.unsol_event = ca0132_unsol_event,
42144351
};
42154352

42164353
static int patch_ca0132(struct hda_codec *codec)
42174354
{
42184355
struct ca0132_spec *spec;
4356+
int err;
42194357

42204358
snd_printdd("patch_ca0132\n");
42214359

@@ -4237,6 +4375,10 @@ static int patch_ca0132(struct hda_codec *codec)
42374375

42384376
ca0132_config(codec);
42394377

4378+
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
4379+
if (err < 0)
4380+
return err;
4381+
42404382
codec->patch_ops = ca0132_patch_ops;
42414383

42424384
return 0;

0 commit comments

Comments
 (0)