Add functions for both reading and writing to the 8051's exram. Also, add a little bit of documentation on how the addresses are segmented.
Signed-off-by: Connor McAdams conmanx360@gmail.com --- sound/pci/hda/patch_ca0132.c | 137 ++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 58 deletions(-)
v2 changes: -Remove conditional mutex.
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 8d2f12f2ce3f..f84815cc8d2f 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -1901,6 +1901,70 @@ static void chipio_8051_write_direct(struct hda_codec *codec, snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, verb, addr); }
+/* + * Writes to the 8051's exram, which has 16-bits of address space. + * Data at addresses 0x2000-0x7fff is mirrored to 0x8000-0xdfff. + * Data at 0x8000-0xdfff can also be used as program memory for the 8051 by + * setting the pmem bank selection SFR. + * 0xe000-0xffff is always mapped as program memory, with only 0xf000-0xffff + * being writable. + */ +static void chipio_8051_set_address(struct hda_codec *codec, unsigned int addr) +{ + unsigned int tmp; + + /* Lower 8-bits. */ + tmp = addr & 0xff; + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, + VENDOR_CHIPIO_8051_ADDRESS_LOW, tmp); + + /* Upper 8-bits. */ + tmp = (addr >> 8) & 0xff; + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, + VENDOR_CHIPIO_8051_ADDRESS_HIGH, tmp); +} + +static void chipio_8051_set_data(struct hda_codec *codec, unsigned int data) +{ + /* 8-bits of data. */ + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, + VENDOR_CHIPIO_8051_DATA_WRITE, data & 0xff); +} + +static unsigned int chipio_8051_get_data(struct hda_codec *codec) +{ + return snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0, + VENDOR_CHIPIO_8051_DATA_READ, 0); +} + +static void chipio_8051_write_exram(struct hda_codec *codec, + unsigned int addr, unsigned int data) +{ + struct ca0132_spec *spec = codec->spec; + + mutex_lock(&spec->chipio_mutex); + + chipio_8051_set_address(codec, addr); + chipio_8051_set_data(codec, data); + + mutex_unlock(&spec->chipio_mutex); +} + +static void chipio_8051_write_exram_no_mutex(struct hda_codec *codec, + unsigned int addr, unsigned int data) +{ + chipio_8051_set_address(codec, addr); + chipio_8051_set_data(codec, data); +} + +/* Readback data from the 8051's exram. No mutex. */ +static void chipio_8051_read_exram(struct hda_codec *codec, + unsigned int addr, unsigned int *data) +{ + chipio_8051_set_address(codec, addr); + *data = chipio_8051_get_data(codec); +} + /* * Enable clocks. */ @@ -7422,18 +7486,10 @@ static void ca0132_init_analog_mic2(struct hda_codec *codec) struct ca0132_spec *spec = codec->spec;
mutex_lock(&spec->chipio_mutex); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x20); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x19); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x00); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x2D); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x19); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x00); + + chipio_8051_write_exram_no_mutex(codec, 0x1920, 0x00); + chipio_8051_write_exram_no_mutex(codec, 0x192d, 0x00); + mutex_unlock(&spec->chipio_mutex); }
@@ -7504,18 +7560,11 @@ static void ca0132_refresh_widget_caps(struct hda_codec *codec) static void chipio_remap_stream(struct hda_codec *codec, const struct chipio_stream_remap_data *remap_data) { - unsigned int i, stream_offset, tmp; + unsigned int i, stream_offset;
/* Get the starting port for the stream to be remapped. */ - tmp = 0x1578 + remap_data->stream_id; - for (i = 0; i < 2; i++) { - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW + i, - ((tmp >> (i * 8)) & 0xff)); - } - - stream_offset = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_READ, 0); + chipio_8051_read_exram(codec, 0x1578 + remap_data->stream_id, + &stream_offset);
/* * Check if the stream's port value is 0xff, because the 8051 may not @@ -7526,9 +7575,8 @@ static void chipio_remap_stream(struct hda_codec *codec, for (i = 0; i < 5; i++) { msleep(25);
- stream_offset = snd_hda_codec_read(codec, - WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_READ, 0); + chipio_8051_read_exram(codec, 0x1578 + remap_data->stream_id, + &stream_offset);
if (stream_offset != 0xff) break; @@ -7863,12 +7911,7 @@ static void ae5_post_dsp_param_setup(struct hda_codec *codec) snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x724, 0x83); chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x92); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0xfa); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x22); + chipio_8051_write_exram(codec, 0xfa92, 0x22); }
static void ae5_post_dsp_pll_setup(struct hda_codec *codec) @@ -8134,12 +8177,7 @@ static void ae7_post_dsp_asi_setup(struct hda_codec *codec) chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0); snd_hda_codec_write(codec, 0x17, 0, 0x794, 0x00);
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x92); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0xfa); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x22); + chipio_8051_write_exram(codec, 0xfa92, 0x22);
ae7_post_dsp_pll_setup(codec); ae7_post_dsp_asi_stream_setup(codec); @@ -9133,12 +9171,7 @@ static void r3d_pre_dsp_setup(struct hda_codec *codec) { chipio_write(codec, 0x18b0a4, 0x000000c2);
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x1E); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x1C); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x5B); + chipio_8051_write_exram(codec, 0x1c1e, 0x5b);
snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x44); @@ -9148,21 +9181,9 @@ static void r3di_pre_dsp_setup(struct hda_codec *codec) { chipio_write(codec, 0x18b0a4, 0x000000c2);
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x1E); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x1C); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x5B); - - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x20); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x19); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x00); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_8051_DATA_WRITE, 0x40); + chipio_8051_write_exram(codec, 0x1c1e, 0x5b); + chipio_8051_write_exram(codec, 0x1920, 0x00); + chipio_8051_write_exram(codec, 0x1921, 0x40);
snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x04);