162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Wolfson WM97xx -- Core device 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2017 Robert Jarzmik 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Features: 862306a36Sopenharmony_ci * - an AC97 audio codec 962306a36Sopenharmony_ci * - a touchscreen driver 1062306a36Sopenharmony_ci * - a GPIO block 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/device.h> 1462306a36Sopenharmony_ci#include <linux/mfd/core.h> 1562306a36Sopenharmony_ci#include <linux/mfd/wm97xx.h> 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci#include <linux/regmap.h> 1862306a36Sopenharmony_ci#include <linux/slab.h> 1962306a36Sopenharmony_ci#include <linux/wm97xx.h> 2062306a36Sopenharmony_ci#include <sound/ac97/codec.h> 2162306a36Sopenharmony_ci#include <sound/ac97/compat.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define WM9705_VENDOR_ID 0x574d4c05 2462306a36Sopenharmony_ci#define WM9712_VENDOR_ID 0x574d4c12 2562306a36Sopenharmony_ci#define WM9713_VENDOR_ID 0x574d4c13 2662306a36Sopenharmony_ci#define WM97xx_VENDOR_ID_MASK 0xffffffff 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistruct wm97xx_priv { 2962306a36Sopenharmony_ci struct regmap *regmap; 3062306a36Sopenharmony_ci struct snd_ac97 *ac97; 3162306a36Sopenharmony_ci struct device *dev; 3262306a36Sopenharmony_ci struct wm97xx_platform_data codec_pdata; 3362306a36Sopenharmony_ci}; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic bool wm97xx_readable_reg(struct device *dev, unsigned int reg) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci switch (reg) { 3862306a36Sopenharmony_ci case AC97_RESET ... AC97_PCM_SURR_DAC_RATE: 3962306a36Sopenharmony_ci case AC97_PCM_LR_ADC_RATE: 4062306a36Sopenharmony_ci case AC97_CENTER_LFE_MASTER: 4162306a36Sopenharmony_ci case AC97_SPDIF ... AC97_LINE1_LEVEL: 4262306a36Sopenharmony_ci case AC97_GPIO_CFG ... 0x5c: 4362306a36Sopenharmony_ci case AC97_CODEC_CLASS_REV ... AC97_PCI_SID: 4462306a36Sopenharmony_ci case 0x74 ... AC97_VENDOR_ID2: 4562306a36Sopenharmony_ci return true; 4662306a36Sopenharmony_ci default: 4762306a36Sopenharmony_ci return false; 4862306a36Sopenharmony_ci } 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic bool wm97xx_writeable_reg(struct device *dev, unsigned int reg) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci switch (reg) { 5462306a36Sopenharmony_ci case AC97_VENDOR_ID1: 5562306a36Sopenharmony_ci case AC97_VENDOR_ID2: 5662306a36Sopenharmony_ci return false; 5762306a36Sopenharmony_ci default: 5862306a36Sopenharmony_ci return wm97xx_readable_reg(dev, reg); 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic const struct reg_default wm9705_reg_defaults[] = { 6362306a36Sopenharmony_ci { 0x02, 0x8000 }, 6462306a36Sopenharmony_ci { 0x04, 0x8000 }, 6562306a36Sopenharmony_ci { 0x06, 0x8000 }, 6662306a36Sopenharmony_ci { 0x0a, 0x8000 }, 6762306a36Sopenharmony_ci { 0x0c, 0x8008 }, 6862306a36Sopenharmony_ci { 0x0e, 0x8008 }, 6962306a36Sopenharmony_ci { 0x10, 0x8808 }, 7062306a36Sopenharmony_ci { 0x12, 0x8808 }, 7162306a36Sopenharmony_ci { 0x14, 0x8808 }, 7262306a36Sopenharmony_ci { 0x16, 0x8808 }, 7362306a36Sopenharmony_ci { 0x18, 0x8808 }, 7462306a36Sopenharmony_ci { 0x1a, 0x0000 }, 7562306a36Sopenharmony_ci { 0x1c, 0x8000 }, 7662306a36Sopenharmony_ci { 0x20, 0x0000 }, 7762306a36Sopenharmony_ci { 0x22, 0x0000 }, 7862306a36Sopenharmony_ci { 0x26, 0x000f }, 7962306a36Sopenharmony_ci { 0x28, 0x0605 }, 8062306a36Sopenharmony_ci { 0x2a, 0x0000 }, 8162306a36Sopenharmony_ci { 0x2c, 0xbb80 }, 8262306a36Sopenharmony_ci { 0x32, 0xbb80 }, 8362306a36Sopenharmony_ci { 0x34, 0x2000 }, 8462306a36Sopenharmony_ci { 0x5a, 0x0000 }, 8562306a36Sopenharmony_ci { 0x5c, 0x0000 }, 8662306a36Sopenharmony_ci { 0x72, 0x0808 }, 8762306a36Sopenharmony_ci { 0x74, 0x0000 }, 8862306a36Sopenharmony_ci { 0x76, 0x0006 }, 8962306a36Sopenharmony_ci { 0x78, 0x0000 }, 9062306a36Sopenharmony_ci { 0x7a, 0x0000 }, 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic const struct regmap_config wm9705_regmap_config = { 9462306a36Sopenharmony_ci .reg_bits = 16, 9562306a36Sopenharmony_ci .reg_stride = 2, 9662306a36Sopenharmony_ci .val_bits = 16, 9762306a36Sopenharmony_ci .max_register = 0x7e, 9862306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci .reg_defaults = wm9705_reg_defaults, 10162306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(wm9705_reg_defaults), 10262306a36Sopenharmony_ci .volatile_reg = regmap_ac97_default_volatile, 10362306a36Sopenharmony_ci .readable_reg = wm97xx_readable_reg, 10462306a36Sopenharmony_ci .writeable_reg = wm97xx_writeable_reg, 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic struct mfd_cell wm9705_cells[] = { 10862306a36Sopenharmony_ci { .name = "wm9705-codec", }, 10962306a36Sopenharmony_ci { .name = "wm97xx-ts", }, 11062306a36Sopenharmony_ci}; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic bool wm9712_volatile_reg(struct device *dev, unsigned int reg) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci switch (reg) { 11562306a36Sopenharmony_ci case AC97_REC_GAIN: 11662306a36Sopenharmony_ci return true; 11762306a36Sopenharmony_ci default: 11862306a36Sopenharmony_ci return regmap_ac97_default_volatile(dev, reg); 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic const struct reg_default wm9712_reg_defaults[] = { 12362306a36Sopenharmony_ci { 0x02, 0x8000 }, 12462306a36Sopenharmony_ci { 0x04, 0x8000 }, 12562306a36Sopenharmony_ci { 0x06, 0x8000 }, 12662306a36Sopenharmony_ci { 0x08, 0x0f0f }, 12762306a36Sopenharmony_ci { 0x0a, 0xaaa0 }, 12862306a36Sopenharmony_ci { 0x0c, 0xc008 }, 12962306a36Sopenharmony_ci { 0x0e, 0x6808 }, 13062306a36Sopenharmony_ci { 0x10, 0xe808 }, 13162306a36Sopenharmony_ci { 0x12, 0xaaa0 }, 13262306a36Sopenharmony_ci { 0x14, 0xad00 }, 13362306a36Sopenharmony_ci { 0x16, 0x8000 }, 13462306a36Sopenharmony_ci { 0x18, 0xe808 }, 13562306a36Sopenharmony_ci { 0x1a, 0x3000 }, 13662306a36Sopenharmony_ci { 0x1c, 0x8000 }, 13762306a36Sopenharmony_ci { 0x20, 0x0000 }, 13862306a36Sopenharmony_ci { 0x22, 0x0000 }, 13962306a36Sopenharmony_ci { 0x26, 0x000f }, 14062306a36Sopenharmony_ci { 0x28, 0x0605 }, 14162306a36Sopenharmony_ci { 0x2a, 0x0410 }, 14262306a36Sopenharmony_ci { 0x2c, 0xbb80 }, 14362306a36Sopenharmony_ci { 0x2e, 0xbb80 }, 14462306a36Sopenharmony_ci { 0x32, 0xbb80 }, 14562306a36Sopenharmony_ci { 0x34, 0x2000 }, 14662306a36Sopenharmony_ci { 0x4c, 0xf83e }, 14762306a36Sopenharmony_ci { 0x4e, 0xffff }, 14862306a36Sopenharmony_ci { 0x50, 0x0000 }, 14962306a36Sopenharmony_ci { 0x52, 0x0000 }, 15062306a36Sopenharmony_ci { 0x56, 0xf83e }, 15162306a36Sopenharmony_ci { 0x58, 0x0008 }, 15262306a36Sopenharmony_ci { 0x5c, 0x0000 }, 15362306a36Sopenharmony_ci { 0x60, 0xb032 }, 15462306a36Sopenharmony_ci { 0x62, 0x3e00 }, 15562306a36Sopenharmony_ci { 0x64, 0x0000 }, 15662306a36Sopenharmony_ci { 0x76, 0x0006 }, 15762306a36Sopenharmony_ci { 0x78, 0x0001 }, 15862306a36Sopenharmony_ci { 0x7a, 0x0000 }, 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic const struct regmap_config wm9712_regmap_config = { 16262306a36Sopenharmony_ci .reg_bits = 16, 16362306a36Sopenharmony_ci .reg_stride = 2, 16462306a36Sopenharmony_ci .val_bits = 16, 16562306a36Sopenharmony_ci .max_register = 0x7e, 16662306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci .reg_defaults = wm9712_reg_defaults, 16962306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(wm9712_reg_defaults), 17062306a36Sopenharmony_ci .volatile_reg = wm9712_volatile_reg, 17162306a36Sopenharmony_ci .readable_reg = wm97xx_readable_reg, 17262306a36Sopenharmony_ci .writeable_reg = wm97xx_writeable_reg, 17362306a36Sopenharmony_ci}; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic struct mfd_cell wm9712_cells[] = { 17662306a36Sopenharmony_ci { .name = "wm9712-codec", }, 17762306a36Sopenharmony_ci { .name = "wm97xx-ts", }, 17862306a36Sopenharmony_ci}; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic const struct reg_default wm9713_reg_defaults[] = { 18162306a36Sopenharmony_ci { 0x02, 0x8080 }, /* Speaker Output Volume */ 18262306a36Sopenharmony_ci { 0x04, 0x8080 }, /* Headphone Output Volume */ 18362306a36Sopenharmony_ci { 0x06, 0x8080 }, /* Out3/OUT4 Volume */ 18462306a36Sopenharmony_ci { 0x08, 0xc880 }, /* Mono Volume */ 18562306a36Sopenharmony_ci { 0x0a, 0xe808 }, /* LINEIN Volume */ 18662306a36Sopenharmony_ci { 0x0c, 0xe808 }, /* DAC PGA Volume */ 18762306a36Sopenharmony_ci { 0x0e, 0x0808 }, /* MIC PGA Volume */ 18862306a36Sopenharmony_ci { 0x10, 0x00da }, /* MIC Routing Control */ 18962306a36Sopenharmony_ci { 0x12, 0x8000 }, /* Record PGA Volume */ 19062306a36Sopenharmony_ci { 0x14, 0xd600 }, /* Record Routing */ 19162306a36Sopenharmony_ci { 0x16, 0xaaa0 }, /* PCBEEP Volume */ 19262306a36Sopenharmony_ci { 0x18, 0xaaa0 }, /* VxDAC Volume */ 19362306a36Sopenharmony_ci { 0x1a, 0xaaa0 }, /* AUXDAC Volume */ 19462306a36Sopenharmony_ci { 0x1c, 0x0000 }, /* Output PGA Mux */ 19562306a36Sopenharmony_ci { 0x1e, 0x0000 }, /* DAC 3D control */ 19662306a36Sopenharmony_ci { 0x20, 0x0f0f }, /* DAC Tone Control*/ 19762306a36Sopenharmony_ci { 0x22, 0x0040 }, /* MIC Input Select & Bias */ 19862306a36Sopenharmony_ci { 0x24, 0x0000 }, /* Output Volume Mapping & Jack */ 19962306a36Sopenharmony_ci { 0x26, 0x7f00 }, /* Powerdown Ctrl/Stat*/ 20062306a36Sopenharmony_ci { 0x28, 0x0405 }, /* Extended Audio ID */ 20162306a36Sopenharmony_ci { 0x2a, 0x0410 }, /* Extended Audio Start/Ctrl */ 20262306a36Sopenharmony_ci { 0x2c, 0xbb80 }, /* Audio DACs Sample Rate */ 20362306a36Sopenharmony_ci { 0x2e, 0xbb80 }, /* AUXDAC Sample Rate */ 20462306a36Sopenharmony_ci { 0x32, 0xbb80 }, /* Audio ADCs Sample Rate */ 20562306a36Sopenharmony_ci { 0x36, 0x4523 }, /* PCM codec control */ 20662306a36Sopenharmony_ci { 0x3a, 0x2000 }, /* SPDIF control */ 20762306a36Sopenharmony_ci { 0x3c, 0xfdff }, /* Powerdown 1 */ 20862306a36Sopenharmony_ci { 0x3e, 0xffff }, /* Powerdown 2 */ 20962306a36Sopenharmony_ci { 0x40, 0x0000 }, /* General Purpose */ 21062306a36Sopenharmony_ci { 0x42, 0x0000 }, /* Fast Power-Up Control */ 21162306a36Sopenharmony_ci { 0x44, 0x0080 }, /* MCLK/PLL Control */ 21262306a36Sopenharmony_ci { 0x46, 0x0000 }, /* MCLK/PLL Control */ 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci { 0x4c, 0xfffe }, /* GPIO Pin Configuration */ 21562306a36Sopenharmony_ci { 0x4e, 0xffff }, /* GPIO Pin Polarity / Type */ 21662306a36Sopenharmony_ci { 0x50, 0x0000 }, /* GPIO Pin Sticky */ 21762306a36Sopenharmony_ci { 0x52, 0x0000 }, /* GPIO Pin Wake-Up */ 21862306a36Sopenharmony_ci /* GPIO Pin Status */ 21962306a36Sopenharmony_ci { 0x56, 0xfffe }, /* GPIO Pin Sharing */ 22062306a36Sopenharmony_ci { 0x58, 0x4000 }, /* GPIO PullUp/PullDown */ 22162306a36Sopenharmony_ci { 0x5a, 0x0000 }, /* Additional Functions 1 */ 22262306a36Sopenharmony_ci { 0x5c, 0x0000 }, /* Additional Functions 2 */ 22362306a36Sopenharmony_ci { 0x60, 0xb032 }, /* ALC Control */ 22462306a36Sopenharmony_ci { 0x62, 0x3e00 }, /* ALC / Noise Gate Control */ 22562306a36Sopenharmony_ci { 0x64, 0x0000 }, /* AUXDAC input control */ 22662306a36Sopenharmony_ci { 0x74, 0x0000 }, /* Digitiser Reg 1 */ 22762306a36Sopenharmony_ci { 0x76, 0x0006 }, /* Digitiser Reg 2 */ 22862306a36Sopenharmony_ci { 0x78, 0x0001 }, /* Digitiser Reg 3 */ 22962306a36Sopenharmony_ci { 0x7a, 0x0000 }, /* Digitiser Read Back */ 23062306a36Sopenharmony_ci}; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cistatic const struct regmap_config wm9713_regmap_config = { 23362306a36Sopenharmony_ci .reg_bits = 16, 23462306a36Sopenharmony_ci .reg_stride = 2, 23562306a36Sopenharmony_ci .val_bits = 16, 23662306a36Sopenharmony_ci .max_register = 0x7e, 23762306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci .reg_defaults = wm9713_reg_defaults, 24062306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(wm9713_reg_defaults), 24162306a36Sopenharmony_ci .volatile_reg = regmap_ac97_default_volatile, 24262306a36Sopenharmony_ci .readable_reg = wm97xx_readable_reg, 24362306a36Sopenharmony_ci .writeable_reg = wm97xx_writeable_reg, 24462306a36Sopenharmony_ci}; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistatic struct mfd_cell wm9713_cells[] = { 24762306a36Sopenharmony_ci { .name = "wm9713-codec", }, 24862306a36Sopenharmony_ci { .name = "wm97xx-ts", }, 24962306a36Sopenharmony_ci}; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic int wm97xx_ac97_probe(struct ac97_codec_device *adev) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci struct wm97xx_priv *wm97xx; 25462306a36Sopenharmony_ci const struct regmap_config *config; 25562306a36Sopenharmony_ci struct wm97xx_platform_data *codec_pdata; 25662306a36Sopenharmony_ci struct mfd_cell *cells; 25762306a36Sopenharmony_ci int ret = -ENODEV, nb_cells, i; 25862306a36Sopenharmony_ci struct wm97xx_pdata *pdata = snd_ac97_codec_get_platdata(adev); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci wm97xx = devm_kzalloc(ac97_codec_dev2dev(adev), 26162306a36Sopenharmony_ci sizeof(*wm97xx), GFP_KERNEL); 26262306a36Sopenharmony_ci if (!wm97xx) 26362306a36Sopenharmony_ci return -ENOMEM; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci wm97xx->dev = ac97_codec_dev2dev(adev); 26662306a36Sopenharmony_ci wm97xx->ac97 = snd_ac97_compat_alloc(adev); 26762306a36Sopenharmony_ci if (IS_ERR(wm97xx->ac97)) 26862306a36Sopenharmony_ci return PTR_ERR(wm97xx->ac97); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci ac97_set_drvdata(adev, wm97xx); 27262306a36Sopenharmony_ci dev_info(wm97xx->dev, "wm97xx core found, id=0x%x\n", 27362306a36Sopenharmony_ci adev->vendor_id); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci codec_pdata = &wm97xx->codec_pdata; 27662306a36Sopenharmony_ci codec_pdata->ac97 = wm97xx->ac97; 27762306a36Sopenharmony_ci codec_pdata->batt_pdata = pdata ? pdata->batt_pdata : NULL; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci switch (adev->vendor_id) { 28062306a36Sopenharmony_ci case WM9705_VENDOR_ID: 28162306a36Sopenharmony_ci config = &wm9705_regmap_config; 28262306a36Sopenharmony_ci cells = wm9705_cells; 28362306a36Sopenharmony_ci nb_cells = ARRAY_SIZE(wm9705_cells); 28462306a36Sopenharmony_ci break; 28562306a36Sopenharmony_ci case WM9712_VENDOR_ID: 28662306a36Sopenharmony_ci config = &wm9712_regmap_config; 28762306a36Sopenharmony_ci cells = wm9712_cells; 28862306a36Sopenharmony_ci nb_cells = ARRAY_SIZE(wm9712_cells); 28962306a36Sopenharmony_ci break; 29062306a36Sopenharmony_ci case WM9713_VENDOR_ID: 29162306a36Sopenharmony_ci config = &wm9713_regmap_config; 29262306a36Sopenharmony_ci cells = wm9713_cells; 29362306a36Sopenharmony_ci nb_cells = ARRAY_SIZE(wm9713_cells); 29462306a36Sopenharmony_ci break; 29562306a36Sopenharmony_ci default: 29662306a36Sopenharmony_ci goto err_free_compat; 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci for (i = 0; i < nb_cells; i++) { 30062306a36Sopenharmony_ci cells[i].platform_data = codec_pdata; 30162306a36Sopenharmony_ci cells[i].pdata_size = sizeof(*codec_pdata); 30262306a36Sopenharmony_ci } 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci codec_pdata->regmap = devm_regmap_init_ac97(wm97xx->ac97, config); 30562306a36Sopenharmony_ci if (IS_ERR(codec_pdata->regmap)) { 30662306a36Sopenharmony_ci ret = PTR_ERR(codec_pdata->regmap); 30762306a36Sopenharmony_ci goto err_free_compat; 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci ret = devm_mfd_add_devices(wm97xx->dev, PLATFORM_DEVID_NONE, 31162306a36Sopenharmony_ci cells, nb_cells, NULL, 0, NULL); 31262306a36Sopenharmony_ci if (ret) 31362306a36Sopenharmony_ci goto err_free_compat; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci return ret; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cierr_free_compat: 31862306a36Sopenharmony_ci snd_ac97_compat_release(wm97xx->ac97); 31962306a36Sopenharmony_ci return ret; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic void wm97xx_ac97_remove(struct ac97_codec_device *adev) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci struct wm97xx_priv *wm97xx = ac97_get_drvdata(adev); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci snd_ac97_compat_release(wm97xx->ac97); 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic const struct ac97_id wm97xx_ac97_ids[] = { 33062306a36Sopenharmony_ci { .id = WM9705_VENDOR_ID, .mask = WM97xx_VENDOR_ID_MASK }, 33162306a36Sopenharmony_ci { .id = WM9712_VENDOR_ID, .mask = WM97xx_VENDOR_ID_MASK }, 33262306a36Sopenharmony_ci { .id = WM9713_VENDOR_ID, .mask = WM97xx_VENDOR_ID_MASK }, 33362306a36Sopenharmony_ci { } 33462306a36Sopenharmony_ci}; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cistatic struct ac97_codec_driver wm97xx_ac97_driver = { 33762306a36Sopenharmony_ci .driver = { 33862306a36Sopenharmony_ci .name = "wm97xx-core", 33962306a36Sopenharmony_ci }, 34062306a36Sopenharmony_ci .probe = wm97xx_ac97_probe, 34162306a36Sopenharmony_ci .remove = wm97xx_ac97_remove, 34262306a36Sopenharmony_ci .id_table = wm97xx_ac97_ids, 34362306a36Sopenharmony_ci}; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic int __init wm97xx_module_init(void) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci return snd_ac97_codec_driver_register(&wm97xx_ac97_driver); 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_cimodule_init(wm97xx_module_init); 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_cistatic void __exit wm97xx_module_exit(void) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci snd_ac97_codec_driver_unregister(&wm97xx_ac97_driver); 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_cimodule_exit(wm97xx_module_exit); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ciMODULE_DESCRIPTION("WM9712, WM9713 core driver"); 35862306a36Sopenharmony_ciMODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>"); 35962306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 36062306a36Sopenharmony_ci 361