1/* 2 * C-Media CMI8788 driver for the MediaTek/TempoTec HiFier Fantasia 3 * 4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de> 5 * 6 * 7 * This driver is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License, version 2. 9 * 10 * This driver is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this driver; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 20/* 21 * CMI8788: 22 * 23 * SPI 0 -> AK4396 24 */ 25 26#include <linux/delay.h> 27#include <linux/pci.h> 28#include <sound/control.h> 29#include <sound/core.h> 30#include <sound/initval.h> 31#include <sound/pcm.h> 32#include <sound/tlv.h> 33#include "oxygen.h" 34#include "ak4396.h" 35 36MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); 37MODULE_DESCRIPTION("TempoTec HiFier driver"); 38MODULE_LICENSE("GPL v2"); 39 40static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; 41static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; 42static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; 43 44module_param_array(index, int, NULL, 0444); 45MODULE_PARM_DESC(index, "card index"); 46module_param_array(id, charp, NULL, 0444); 47MODULE_PARM_DESC(id, "ID string"); 48module_param_array(enable, bool, NULL, 0444); 49MODULE_PARM_DESC(enable, "enable card"); 50 51static DEFINE_PCI_DEVICE_TABLE(hifier_ids) = { 52 { OXYGEN_PCI_SUBID(0x14c3, 0x1710) }, 53 { OXYGEN_PCI_SUBID(0x14c3, 0x1711) }, 54 { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, 55 { } 56}; 57MODULE_DEVICE_TABLE(pci, hifier_ids); 58 59struct hifier_data { 60 u8 ak4396_regs[5]; 61}; 62 63static void ak4396_write(struct oxygen *chip, u8 reg, u8 value) 64{ 65 struct hifier_data *data = chip->model_data; 66 67 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | 68 OXYGEN_SPI_DATA_LENGTH_2 | 69 OXYGEN_SPI_CLOCK_160 | 70 (0 << OXYGEN_SPI_CODEC_SHIFT) | 71 OXYGEN_SPI_CEN_LATCH_CLOCK_HI, 72 AK4396_WRITE | (reg << 8) | value); 73 data->ak4396_regs[reg] = value; 74} 75 76static void ak4396_write_cached(struct oxygen *chip, u8 reg, u8 value) 77{ 78 struct hifier_data *data = chip->model_data; 79 80 if (value != data->ak4396_regs[reg]) 81 ak4396_write(chip, reg, value); 82} 83 84static void hifier_registers_init(struct oxygen *chip) 85{ 86 struct hifier_data *data = chip->model_data; 87 88 ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); 89 ak4396_write(chip, AK4396_CONTROL_2, 90 data->ak4396_regs[AK4396_CONTROL_2]); 91 ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM); 92 ak4396_write(chip, AK4396_LCH_ATT, chip->dac_volume[0]); 93 ak4396_write(chip, AK4396_RCH_ATT, chip->dac_volume[1]); 94} 95 96static void hifier_init(struct oxygen *chip) 97{ 98 struct hifier_data *data = chip->model_data; 99 100 data->ak4396_regs[AK4396_CONTROL_2] = 101 AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; 102 hifier_registers_init(chip); 103 104 snd_component_add(chip->card, "AK4396"); 105 snd_component_add(chip->card, "CS5340"); 106} 107 108static void hifier_cleanup(struct oxygen *chip) 109{ 110} 111 112static void hifier_resume(struct oxygen *chip) 113{ 114 hifier_registers_init(chip); 115} 116 117static void set_ak4396_params(struct oxygen *chip, 118 struct snd_pcm_hw_params *params) 119{ 120 struct hifier_data *data = chip->model_data; 121 u8 value; 122 123 value = data->ak4396_regs[AK4396_CONTROL_2] & ~AK4396_DFS_MASK; 124 if (params_rate(params) <= 54000) 125 value |= AK4396_DFS_NORMAL; 126 else if (params_rate(params) <= 108000) 127 value |= AK4396_DFS_DOUBLE; 128 else 129 value |= AK4396_DFS_QUAD; 130 131 msleep(1); /* wait for the new MCLK to become stable */ 132 133 if (value != data->ak4396_regs[AK4396_CONTROL_2]) { 134 ak4396_write(chip, AK4396_CONTROL_1, 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 142static 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]); 146} 147 148static void update_ak4396_mute(struct oxygen *chip) 149{ 150 struct hifier_data *data = chip->model_data; 151 u8 value; 152 153 value = data->ak4396_regs[AK4396_CONTROL_2] & ~AK4396_SMUTE; 154 if (chip->dac_mute) 155 value |= AK4396_SMUTE; 156 ak4396_write_cached(chip, AK4396_CONTROL_2, value); 157} 158 159static void set_cs5340_params(struct oxygen *chip, 160 struct snd_pcm_hw_params *params) 161{ 162} 163 164static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); 165 166static const struct oxygen_model model_hifier = { 167 .shortname = "C-Media CMI8787", 168 .longname = "C-Media Oxygen HD Audio", 169 .chip = "CMI8788", 170 .init = hifier_init, 171 .cleanup = hifier_cleanup, 172 .resume = hifier_resume, 173 .get_i2s_mclk = oxygen_default_i2s_mclk, 174 .set_dac_params = set_ak4396_params, 175 .set_adc_params = set_cs5340_params, 176 .update_dac_volume = update_ak4396_volume, 177 .update_dac_mute = update_ak4396_mute, 178 .dac_tlv = ak4396_db_scale, 179 .model_data_size = sizeof(struct hifier_data), 180 .device_config = PLAYBACK_0_TO_I2S | 181 PLAYBACK_1_TO_SPDIF | 182 CAPTURE_0_FROM_I2S_1, 183 .dac_channels = 2, 184 .dac_volume_min = 0, 185 .dac_volume_max = 255, 186 .function_flags = OXYGEN_FUNCTION_SPI, 187 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, 188 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, 189}; 190 191static int __devinit get_hifier_model(struct oxygen *chip, 192 const struct pci_device_id *id) 193{ 194 chip->model = model_hifier; 195 return 0; 196} 197 198static int __devinit hifier_probe(struct pci_dev *pci, 199 const struct pci_device_id *pci_id) 200{ 201 static int dev; 202 int err; 203 204 if (dev >= SNDRV_CARDS) 205 return -ENODEV; 206 if (!enable[dev]) { 207 ++dev; 208 return -ENOENT; 209 } 210 err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, 211 hifier_ids, get_hifier_model); 212 if (err >= 0) 213 ++dev; 214 return err; 215} 216 217static struct pci_driver hifier_driver = { 218 .name = "CMI8787HiFier", 219 .id_table = hifier_ids, 220 .probe = hifier_probe, 221 .remove = __devexit_p(oxygen_pci_remove), 222#ifdef CONFIG_PM 223 .suspend = oxygen_pci_suspend, 224 .resume = oxygen_pci_resume, 225#endif 226}; 227 228static int __init alsa_card_hifier_init(void) 229{ 230 return pci_register_driver(&hifier_driver); 231} 232 233static void __exit alsa_card_hifier_exit(void) 234{ 235 pci_unregister_driver(&hifier_driver); 236} 237 238module_init(alsa_card_hifier_init) 239module_exit(alsa_card_hifier_exit) 240