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 84ef13183419..e3c229b63311 100644 --- a/sound/pci/oxygen/hifier.c +++ b/sound/pci/oxygen/hifier.c | |||
@@ -17,6 +17,12 @@ | |||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | 19 | ||
20 | /* | ||
21 | * CMI8788: | ||
22 | * | ||
23 | * SPI 0 -> AK4396 | ||
24 | */ | ||
25 | |||
20 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
21 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
22 | #include <sound/control.h> | 28 | #include <sound/control.h> |
@@ -51,23 +57,28 @@ static struct pci_device_id hifier_ids[] __devinitdata = { | |||
51 | MODULE_DEVICE_TABLE(pci, hifier_ids); | 57 | MODULE_DEVICE_TABLE(pci, hifier_ids); |
52 | 58 | ||
53 | struct hifier_data { | 59 | struct hifier_data { |
54 | u8 ak4396_ctl2; | 60 | u8 ak4396_regs[5]; |
55 | }; | 61 | }; |
56 | 62 | ||
57 | static void ak4396_write(struct oxygen *chip, u8 reg, u8 value) | 63 | static void ak4396_write(struct oxygen *chip, u8 reg, u8 value) |
58 | { | 64 | { |
65 | struct hifier_data *data = chip->model_data; | ||
66 | |||
59 | oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | | 67 | oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | |
60 | OXYGEN_SPI_DATA_LENGTH_2 | | 68 | OXYGEN_SPI_DATA_LENGTH_2 | |
61 | OXYGEN_SPI_CLOCK_160 | | 69 | OXYGEN_SPI_CLOCK_160 | |
62 | (0 << OXYGEN_SPI_CODEC_SHIFT) | | 70 | (0 << OXYGEN_SPI_CODEC_SHIFT) | |
63 | OXYGEN_SPI_CEN_LATCH_CLOCK_HI, | 71 | OXYGEN_SPI_CEN_LATCH_CLOCK_HI, |
64 | AK4396_WRITE | (reg << 8) | value); | 72 | AK4396_WRITE | (reg << 8) | value); |
73 | data->ak4396_regs[reg] = value; | ||
65 | } | 74 | } |
66 | 75 | ||
67 | static void update_ak4396_volume(struct oxygen *chip) | 76 | static void ak4396_write_cached(struct oxygen *chip, u8 reg, u8 value) |
68 | { | 77 | { |
69 | ak4396_write(chip, AK4396_LCH_ATT, chip->dac_volume[0]); | 78 | struct hifier_data *data = chip->model_data; |
70 | ak4396_write(chip, AK4396_RCH_ATT, chip->dac_volume[1]); | 79 | |
80 | if (value != data->ak4396_regs[reg]) | ||
81 | ak4396_write(chip, reg, value); | ||
71 | } | 82 | } |
72 | 83 | ||
73 | static void hifier_registers_init(struct oxygen *chip) | 84 | static void hifier_registers_init(struct oxygen *chip) |
@@ -75,16 +86,19 @@ static void hifier_registers_init(struct oxygen *chip) | |||
75 | struct hifier_data *data = chip->model_data; | 86 | struct hifier_data *data = chip->model_data; |
76 | 87 | ||
77 | ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); | 88 | ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); |
78 | ak4396_write(chip, AK4396_CONTROL_2, data->ak4396_ctl2); | 89 | ak4396_write(chip, AK4396_CONTROL_2, |
90 | data->ak4396_regs[AK4396_CONTROL_2]); | ||
79 | ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM); | 91 | ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM); |
80 | update_ak4396_volume(chip); | 92 | ak4396_write(chip, AK4396_LCH_ATT, chip->dac_volume[0]); |
93 | ak4396_write(chip, AK4396_RCH_ATT, chip->dac_volume[1]); | ||
81 | } | 94 | } |
82 | 95 | ||
83 | static void hifier_init(struct oxygen *chip) | 96 | static void hifier_init(struct oxygen *chip) |
84 | { | 97 | { |
85 | struct hifier_data *data = chip->model_data; | 98 | struct hifier_data *data = chip->model_data; |
86 | 99 | ||
87 | data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; | 100 | data->ak4396_regs[AK4396_CONTROL_2] = |
101 | AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; | ||
88 | hifier_registers_init(chip); | 102 | hifier_registers_init(chip); |
89 | 103 | ||
90 | snd_component_add(chip->card, "AK4396"); | 104 | snd_component_add(chip->card, "AK4396"); |
@@ -106,20 +120,29 @@ static void set_ak4396_params(struct oxygen *chip, | |||
106 | struct hifier_data *data = chip->model_data; | 120 | struct hifier_data *data = chip->model_data; |
107 | u8 value; | 121 | u8 value; |
108 | 122 | ||
109 | value = data->ak4396_ctl2 & ~AK4396_DFS_MASK; | 123 | value = data->ak4396_regs[AK4396_CONTROL_2] & ~AK4396_DFS_MASK; |
110 | if (params_rate(params) <= 54000) | 124 | if (params_rate(params) <= 54000) |
111 | value |= AK4396_DFS_NORMAL; | 125 | value |= AK4396_DFS_NORMAL; |
112 | else if (params_rate(params) <= 108000) | 126 | else if (params_rate(params) <= 108000) |
113 | value |= AK4396_DFS_DOUBLE; | 127 | value |= AK4396_DFS_DOUBLE; |
114 | else | 128 | else |
115 | value |= AK4396_DFS_QUAD; | 129 | value |= AK4396_DFS_QUAD; |
116 | data->ak4396_ctl2 = value; | ||
117 | 130 | ||
118 | msleep(1); /* wait for the new MCLK to become stable */ | 131 | msleep(1); /* wait for the new MCLK to become stable */ |
119 | 132 | ||
120 | ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB); | 133 | if (value != data->ak4396_regs[AK4396_CONTROL_2]) { |
121 | ak4396_write(chip, AK4396_CONTROL_2, value); | 134 | ak4396_write(chip, AK4396_CONTROL_1, |
122 | ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); | 135 | AK4396_DIF_24_MSB); |
136 | ak4396_write(chip, AK4396_CONTROL_2, value); | ||
137 | ak4396_write(chip, AK4396_CONTROL_1, | ||
138 | AK4396_DIF_24_MSB | AK4396_RSTN); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | static void update_ak4396_volume(struct oxygen *chip) | ||
143 | { | ||
144 | ak4396_write_cached(chip, AK4396_LCH_ATT, chip->dac_volume[0]); | ||
145 | ak4396_write_cached(chip, AK4396_RCH_ATT, chip->dac_volume[1]); | ||
123 | } | 146 | } |
124 | 147 | ||
125 | static void update_ak4396_mute(struct oxygen *chip) | 148 | static void update_ak4396_mute(struct oxygen *chip) |
@@ -127,11 +150,10 @@ static void update_ak4396_mute(struct oxygen *chip) | |||
127 | struct hifier_data *data = chip->model_data; | 150 | struct hifier_data *data = chip->model_data; |
128 | u8 value; | 151 | u8 value; |
129 | 152 | ||
130 | value = data->ak4396_ctl2 & ~AK4396_SMUTE; | 153 | value = data->ak4396_regs[AK4396_CONTROL_2] & ~AK4396_SMUTE; |
131 | if (chip->dac_mute) | 154 | if (chip->dac_mute) |
132 | value |= AK4396_SMUTE; | 155 | value |= AK4396_SMUTE; |
133 | data->ak4396_ctl2 = value; | 156 | ak4396_write_cached(chip, AK4396_CONTROL_2, value); |
134 | ak4396_write(chip, AK4396_CONTROL_2, value); | ||
135 | } | 157 | } |
136 | 158 | ||
137 | static void set_cs5340_params(struct oxygen *chip, | 159 | static void set_cs5340_params(struct oxygen *chip, |
@@ -141,21 +163,14 @@ static void set_cs5340_params(struct oxygen *chip, | |||
141 | 163 | ||
142 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); | 164 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); |
143 | 165 | ||
144 | static int hifier_control_filter(struct snd_kcontrol_new *template) | ||
145 | { | ||
146 | if (!strcmp(template->name, "Stereo Upmixing")) | ||
147 | return 1; /* stereo only - we don't need upmixing */ | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static const struct oxygen_model model_hifier = { | 166 | static const struct oxygen_model model_hifier = { |
152 | .shortname = "C-Media CMI8787", | 167 | .shortname = "C-Media CMI8787", |
153 | .longname = "C-Media Oxygen HD Audio", | 168 | .longname = "C-Media Oxygen HD Audio", |
154 | .chip = "CMI8788", | 169 | .chip = "CMI8788", |
155 | .init = hifier_init, | 170 | .init = hifier_init, |
156 | .control_filter = hifier_control_filter, | ||
157 | .cleanup = hifier_cleanup, | 171 | .cleanup = hifier_cleanup, |
158 | .resume = hifier_resume, | 172 | .resume = hifier_resume, |
173 | .get_i2s_mclk = oxygen_default_i2s_mclk, | ||
159 | .set_dac_params = set_ak4396_params, | 174 | .set_dac_params = set_ak4396_params, |
160 | .set_adc_params = set_cs5340_params, | 175 | .set_adc_params = set_cs5340_params, |
161 | .update_dac_volume = update_ak4396_volume, | 176 | .update_dac_volume = update_ak4396_volume, |