Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr>
0004  */
0005 
0006 #include <linux/list.h>
0007 #include <linux/slab.h>
0008 #include <sound/ac97/codec.h>
0009 #include <sound/ac97/compat.h>
0010 #include <sound/ac97/controller.h>
0011 #include <sound/soc.h>
0012 
0013 #include "ac97_core.h"
0014 
0015 static void compat_ac97_release(struct device *dev)
0016 {
0017     kfree(to_ac97_t(dev));
0018 }
0019 
0020 static void compat_ac97_reset(struct snd_ac97 *ac97)
0021 {
0022     struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
0023     struct ac97_controller *actrl = adev->ac97_ctrl;
0024 
0025     if (actrl->ops->reset)
0026         actrl->ops->reset(actrl);
0027 }
0028 
0029 static void compat_ac97_warm_reset(struct snd_ac97 *ac97)
0030 {
0031     struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
0032     struct ac97_controller *actrl = adev->ac97_ctrl;
0033 
0034     if (actrl->ops->warm_reset)
0035         actrl->ops->warm_reset(actrl);
0036 }
0037 
0038 static void compat_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
0039                   unsigned short val)
0040 {
0041     struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
0042     struct ac97_controller *actrl = adev->ac97_ctrl;
0043 
0044     actrl->ops->write(actrl, ac97->num, reg, val);
0045 }
0046 
0047 static unsigned short compat_ac97_read(struct snd_ac97 *ac97,
0048                        unsigned short reg)
0049 {
0050     struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
0051     struct ac97_controller *actrl = adev->ac97_ctrl;
0052 
0053     return actrl->ops->read(actrl, ac97->num, reg);
0054 }
0055 
0056 static const struct snd_ac97_bus_ops compat_snd_ac97_bus_ops = {
0057     .reset = compat_ac97_reset,
0058     .warm_reset = compat_ac97_warm_reset,
0059     .write = compat_ac97_write,
0060     .read = compat_ac97_read,
0061 };
0062 
0063 static struct snd_ac97_bus compat_soc_ac97_bus = {
0064     .ops = &compat_snd_ac97_bus_ops,
0065 };
0066 
0067 struct snd_ac97 *snd_ac97_compat_alloc(struct ac97_codec_device *adev)
0068 {
0069     struct snd_ac97 *ac97;
0070     int ret;
0071 
0072     ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
0073     if (ac97 == NULL)
0074         return ERR_PTR(-ENOMEM);
0075 
0076     ac97->private_data = adev;
0077     ac97->bus = &compat_soc_ac97_bus;
0078 
0079     ac97->dev.parent = &adev->dev;
0080     ac97->dev.release = compat_ac97_release;
0081     dev_set_name(&ac97->dev, "%s-compat", dev_name(&adev->dev));
0082     ret = device_register(&ac97->dev);
0083     if (ret) {
0084         put_device(&ac97->dev);
0085         return ERR_PTR(ret);
0086     }
0087 
0088     return ac97;
0089 }
0090 EXPORT_SYMBOL_GPL(snd_ac97_compat_alloc);
0091 
0092 void snd_ac97_compat_release(struct snd_ac97 *ac97)
0093 {
0094     device_unregister(&ac97->dev);
0095 }
0096 EXPORT_SYMBOL_GPL(snd_ac97_compat_release);
0097 
0098 int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,
0099     unsigned int id_mask)
0100 {
0101     struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
0102     struct ac97_controller *actrl = adev->ac97_ctrl;
0103     unsigned int scanned;
0104 
0105     if (try_warm) {
0106         compat_ac97_warm_reset(ac97);
0107         scanned = snd_ac97_bus_scan_one(actrl, adev->num);
0108         if (ac97_ids_match(scanned, adev->vendor_id, id_mask))
0109             return 1;
0110     }
0111 
0112     compat_ac97_reset(ac97);
0113     compat_ac97_warm_reset(ac97);
0114     scanned = snd_ac97_bus_scan_one(actrl, adev->num);
0115     if (ac97_ids_match(scanned, adev->vendor_id, id_mask))
0116         return 0;
0117 
0118     return -ENODEV;
0119 }
0120 EXPORT_SYMBOL_GPL(snd_ac97_reset);