Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 353260
b: refs/heads/master
c: a73d511
h: refs/heads/master
v: v3
  • Loading branch information
Ian Minett authored and Takashi Iwai committed Jan 15, 2013
1 parent 762a262 commit 54339c4
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 825315bc5b5c33e5af5124ff100ef05a30ad722f
refs/heads/master: a73d511c4867c5aa75a9ab50f7e73d5086c48cda
142 changes: 142 additions & 0 deletions trunk/sound/pci/hda/patch_ca0132.c
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,59 @@ static int dspio_write_multiple(struct hda_codec *codec,
return status;
}

static int dspio_read(struct hda_codec *codec, unsigned int *data)
{
int status;

status = dspio_send(codec, VENDOR_DSPIO_SCP_POST_READ_DATA, 0);
if (status == -EIO)
return status;

status = dspio_send(codec, VENDOR_DSPIO_STATUS, 0);
if (status == -EIO ||
status == VENDOR_STATUS_DSPIO_SCP_RESPONSE_QUEUE_EMPTY)
return -EIO;

*data = snd_hda_codec_read(codec, WIDGET_DSP_CTRL, 0,
VENDOR_DSPIO_SCP_READ_DATA, 0);

return 0;
}

static int dspio_read_multiple(struct hda_codec *codec, unsigned int *buffer,
unsigned int *buf_size, unsigned int size_count)
{
int status = 0;
unsigned int size = *buf_size;
unsigned int count;
unsigned int skip_count;
unsigned int dummy;

if ((buffer == NULL))
return -1;

count = 0;
while (count < size && count < size_count) {
status = dspio_read(codec, buffer++);
if (status != 0)
break;
count++;
}

skip_count = count;
if (status == 0) {
while (skip_count < size) {
status = dspio_read(codec, &dummy);
if (status != 0)
break;
skip_count++;
}
}
*buf_size = count;

return status;
}

/*
* Construct the SCP header using corresponding fields
*/
Expand Down Expand Up @@ -1231,6 +1284,38 @@ struct scp_msg {
unsigned int data[SCP_MAX_DATA_WORDS];
};

static void dspio_clear_response_queue(struct hda_codec *codec)
{
unsigned int dummy = 0;
int status = -1;

/* clear all from the response queue */
do {
status = dspio_read(codec, &dummy);
} while (status == 0);
}

static int dspio_get_response_data(struct hda_codec *codec)
{
struct ca0132_spec *spec = codec->spec;
unsigned int data = 0;
unsigned int count;

if (dspio_read(codec, &data) < 0)
return -EIO;

if ((data & 0x00ffffff) == spec->wait_scp_header) {
spec->scp_resp_header = data;
spec->scp_resp_count = data >> 27;
count = spec->wait_num_data;
dspio_read_multiple(codec, spec->scp_resp_data,
&spec->scp_resp_count, count);
return 0;
}

return -EIO;
}

/*
* Send SCP message to DSP
*/
Expand Down Expand Up @@ -3743,6 +3828,12 @@ static int ca0132_build_controls(struct hda_codec *codec)
return 0;
}

static void ca0132_init_unsol(struct hda_codec *codec)
{
snd_hda_jack_detect_enable(codec, UNSOL_TAG_HP, UNSOL_TAG_HP);
snd_hda_jack_detect_enable(codec, UNSOL_TAG_AMIC1, UNSOL_TAG_AMIC1);
}

static void refresh_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir)
{
unsigned int caps;
Expand Down Expand Up @@ -4152,6 +4243,47 @@ static void ca0132_download_dsp(struct hda_codec *codec)
ca0132_set_dsp_msr(codec, true);
}

static void ca0132_process_dsp_response(struct hda_codec *codec)
{
struct ca0132_spec *spec = codec->spec;

snd_printdd(KERN_INFO "ca0132_process_dsp_response\n");
if (spec->wait_scp) {
if (dspio_get_response_data(codec) >= 0)
spec->wait_scp = 0;
}

dspio_clear_response_queue(codec);
}

static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res)
{
snd_printdd(KERN_INFO "ca0132_unsol_event: 0x%x\n", res);


if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) {
ca0132_process_dsp_response(codec);
} else {
res = snd_hda_jack_get_action(codec,
(res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f);

snd_printdd(KERN_INFO "snd_hda_jack_get_action: 0x%x\n", res);

switch (res) {
case UNSOL_TAG_HP:
ca0132_select_out(codec);
snd_hda_jack_report_sync(codec);
break;
case UNSOL_TAG_AMIC1:
ca0132_select_mic(codec);
snd_hda_jack_report_sync(codec);
break;
default:
break;
}
}
}

static int ca0132_init(struct hda_codec *codec)
{
struct ca0132_spec *spec = codec->spec;
Expand Down Expand Up @@ -4187,9 +4319,13 @@ static int ca0132_init(struct hda_codec *codec)
for (i = 0; i < spec->num_init_verbs; i++)
snd_hda_sequence_write(codec, spec->init_verbs[i]);

ca0132_init_unsol(codec);

ca0132_select_out(codec);
ca0132_select_mic(codec);

snd_hda_jack_report_sync(codec);

snd_hda_power_down(codec);

return 0;
Expand All @@ -4211,11 +4347,13 @@ static struct hda_codec_ops ca0132_patch_ops = {
.build_pcms = ca0132_build_pcms,
.init = ca0132_init,
.free = ca0132_free,
.unsol_event = ca0132_unsol_event,
};

static int patch_ca0132(struct hda_codec *codec)
{
struct ca0132_spec *spec;
int err;

snd_printdd("patch_ca0132\n");

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

ca0132_config(codec);

err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
if (err < 0)
return err;

codec->patch_ops = ca0132_patch_ops;

return 0;
Expand Down

0 comments on commit 54339c4

Please sign in to comment.