diff options
Diffstat (limited to 'sound/pci/oxygen/hifier.c')
-rw-r--r-- | sound/pci/oxygen/hifier.c | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c index 84ef131..e3c229b 100644 --- a/sound/pci/oxygen/hifier.c +++ b/sound/pci/oxygen/hifier.c @@ -17,6 +17,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* + * CMI8788: + * + * SPI 0 -> AK4396 + */ + #include <linux/delay.h> #include <linux/pci.h> #include <sound/control.h> @@ -51,23 +57,28 @@ static struct pci_device_id hifier_ids[] __devinitdata = { MODULE_DEVICE_TABLE(pci, hifier_ids); struct hifier_data { - u8 ak4396_ctl2; + u8 ak4396_regs[5]; }; static void ak4396_write(struct oxygen *chip, u8 reg, u8 value) { + struct hifier_data *data = chip->model_data; + oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | OXYGEN_SPI_DATA_LENGTH_2 | OXYGEN_SPI_CLOCK_160 | (0 << OXYGEN_SPI_CODEC_SHIFT) | OXYGEN_SPI_CEN_LATCH_CLOCK_HI, AK4396_WRITE | (reg << 8) | value); + data->ak4396_regs[reg] = value; } -static void update_ak4396_volume(struct oxygen *chip) +static void ak4396_write_cached(struct oxygen *chip, u8 reg, u8 value) { - ak4396_write(chip, AK4396_LCH_ATT, chip->dac_volume[0]); - ak4396_write(chip, AK4396_RCH_ATT, chip->dac_volume[1]); + struct hifier_data *data = chip->model_data; + + if (value != data->ak4396_regs[reg]) + ak4396_write(chip, reg, value); } static void hifier_registers_init(struct oxygen *chip) @@ -75,16 +86,19 @@ static void hifier_registers_init(struct oxygen *chip) struct hifier_data *data = chip->model_data; ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); - ak4396_write(chip, AK4396_CONTROL_2, data->ak4396_ctl2); + ak4396_write(chip, AK4396_CONTROL_2, + data->ak4396_regs[AK4396_CONTROL_2]); ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM); - update_ak4396_volume(chip); + ak4396_write(chip, AK4396_LCH_ATT, chip->dac_volume[0]); + ak4396_write(chip, AK4396_RCH_ATT, chip->dac_volume[1]); } static void hifier_init(struct oxygen *chip) { struct hifier_data *data = chip->model_data; - data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; + data->ak4396_regs[AK4396_CONTROL_2] = + AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; hifier_registers_init(chip); snd_component_add(chip->card, "AK4396"); @@ -106,20 +120,29 @@ static void set_ak4396_params(struct oxygen *chip, struct hifier_data *data = chip->model_data; u8 value; - value = data->ak4396_ctl2 & ~AK4396_DFS_MASK; + value = data->ak4396_regs[AK4396_CONTROL_2] & ~AK4396_DFS_MASK; if (params_rate(params) <= 54000) value |= AK4396_DFS_NORMAL; else if (params_rate(params) <= 108000) value |= AK4396_DFS_DOUBLE; else value |= AK4396_DFS_QUAD; - data->ak4396_ctl2 = value; msleep(1); /* wait for the new MCLK to become stable */ - ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB); - ak4396_write(chip, AK4396_CONTROL_2, value); - ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); + if (value != data->ak4396_regs[AK4396_CONTROL_2]) { + ak4396_write(chip, AK4396_CONTROL_1, + AK4396_DIF_24_MSB); + ak4396_write(chip, AK4396_CONTROL_2, value); + ak4396_write(chip, AK4396_CONTROL_1, + AK4396_DIF_24_MSB | AK4396_RSTN); + } +} + +static void update_ak4396_volume(struct oxygen *chip) +{ + ak4396_write_cached(chip, AK4396_LCH_ATT, chip->dac_volume[0]); + ak4396_write_cached(chip, AK4396_RCH_ATT, chip->dac_volume[1]); } static void update_ak4396_mute(struct oxygen *chip) @@ -127,11 +150,10 @@ static void update_ak4396_mute(struct oxygen *chip) struct hifier_data *data = chip->model_data; u8 value; - value = data->ak4396_ctl2 & ~AK4396_SMUTE; + value = data->ak4396_regs[AK4396_CONTROL_2] & ~AK4396_SMUTE; if (chip->dac_mute) value |= AK4396_SMUTE; - data->ak4396_ctl2 = value; - ak4396_write(chip, AK4396_CONTROL_2, value); + ak4396_write_cached(chip, AK4396_CONTROL_2, value); } static void set_cs5340_params(struct oxygen *chip, @@ -141,21 +163,14 @@ static void set_cs5340_params(struct oxygen *chip, static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); -static int hifier_control_filter(struct snd_kcontrol_new *template) -{ - if (!strcmp(template->name, "Stereo Upmixing")) - return 1; /* stereo only - we don't need upmixing */ - return 0; -} - static const struct oxygen_model model_hifier = { .shortname = "C-Media CMI8787", .longname = "C-Media Oxygen HD Audio", .chip = "CMI8788", .init = hifier_init, - .control_filter = hifier_control_filter, .cleanup = hifier_cleanup, .resume = hifier_resume, + .get_i2s_mclk = oxygen_default_i2s_mclk, .set_dac_params = set_ak4396_params, .set_adc_params = set_cs5340_params, .update_dac_volume = update_ak4396_volume, |