1 /* 2 * Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9 #include <linux/list.h> 10 #include <linux/slab.h> 11 #include <sound/ac97/codec.h> 12 #include <sound/ac97/compat.h> 13 #include <sound/ac97/controller.h> 14 #include <sound/soc.h> 15 16 #include "ac97_core.h" 17 18 static void compat_ac97_reset(struct snd_ac97 *ac97) 19 { 20 struct ac97_codec_device *adev = to_ac97_device(ac97->private_data); 21 struct ac97_controller *actrl = adev->ac97_ctrl; 22 23 if (actrl->ops->reset) 24 actrl->ops->reset(actrl); 25 } 26 27 static void compat_ac97_warm_reset(struct snd_ac97 *ac97) 28 { 29 struct ac97_codec_device *adev = to_ac97_device(ac97->private_data); 30 struct ac97_controller *actrl = adev->ac97_ctrl; 31 32 if (actrl->ops->warm_reset) 33 actrl->ops->warm_reset(actrl); 34 } 35 36 static void compat_ac97_write(struct snd_ac97 *ac97, unsigned short reg, 37 unsigned short val) 38 { 39 struct ac97_codec_device *adev = to_ac97_device(ac97->private_data); 40 struct ac97_controller *actrl = adev->ac97_ctrl; 41 42 actrl->ops->write(actrl, ac97->num, reg, val); 43 } 44 45 static unsigned short compat_ac97_read(struct snd_ac97 *ac97, 46 unsigned short reg) 47 { 48 struct ac97_codec_device *adev = to_ac97_device(ac97->private_data); 49 struct ac97_controller *actrl = adev->ac97_ctrl; 50 51 return actrl->ops->read(actrl, ac97->num, reg); 52 } 53 54 static struct snd_ac97_bus_ops compat_snd_ac97_bus_ops = { 55 .reset = compat_ac97_reset, 56 .warm_reset = compat_ac97_warm_reset, 57 .write = compat_ac97_write, 58 .read = compat_ac97_read, 59 }; 60 61 static struct snd_ac97_bus compat_soc_ac97_bus = { 62 .ops = &compat_snd_ac97_bus_ops, 63 }; 64 65 struct snd_ac97 *snd_ac97_compat_alloc(struct ac97_codec_device *adev) 66 { 67 struct snd_ac97 *ac97; 68 69 ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); 70 if (ac97 == NULL) 71 return ERR_PTR(-ENOMEM); 72 73 ac97->dev = adev->dev; 74 ac97->private_data = adev; 75 ac97->bus = &compat_soc_ac97_bus; 76 return ac97; 77 } 78 EXPORT_SYMBOL_GPL(snd_ac97_compat_alloc); 79 80 void snd_ac97_compat_release(struct snd_ac97 *ac97) 81 { 82 kfree(ac97); 83 } 84 EXPORT_SYMBOL_GPL(snd_ac97_compat_release); 85 86 int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id, 87 unsigned int id_mask) 88 { 89 struct ac97_codec_device *adev = to_ac97_device(ac97->private_data); 90 struct ac97_controller *actrl = adev->ac97_ctrl; 91 unsigned int scanned; 92 93 if (try_warm) { 94 compat_ac97_warm_reset(ac97); 95 scanned = snd_ac97_bus_scan_one(actrl, adev->num); 96 if (ac97_ids_match(scanned, adev->vendor_id, id_mask)) 97 return 1; 98 } 99 100 compat_ac97_reset(ac97); 101 compat_ac97_warm_reset(ac97); 102 scanned = snd_ac97_bus_scan_one(actrl, adev->num); 103 if (ac97_ids_match(scanned, adev->vendor_id, id_mask)) 104 return 0; 105 106 return -ENODEV; 107 } 108 EXPORT_SYMBOL_GPL(snd_ac97_reset); 109