linux/sound/ac97/snd_ac97_compat.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr>
   4 */
   5
   6#include <linux/list.h>
   7#include <linux/slab.h>
   8#include <sound/ac97/codec.h>
   9#include <sound/ac97/compat.h>
  10#include <sound/ac97/controller.h>
  11#include <sound/soc.h>
  12
  13#include "ac97_core.h"
  14
  15static void compat_ac97_release(struct device *dev)
  16{
  17        kfree(to_ac97_t(dev));
  18}
  19
  20static void compat_ac97_reset(struct snd_ac97 *ac97)
  21{
  22        struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
  23        struct ac97_controller *actrl = adev->ac97_ctrl;
  24
  25        if (actrl->ops->reset)
  26                actrl->ops->reset(actrl);
  27}
  28
  29static void compat_ac97_warm_reset(struct snd_ac97 *ac97)
  30{
  31        struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
  32        struct ac97_controller *actrl = adev->ac97_ctrl;
  33
  34        if (actrl->ops->warm_reset)
  35                actrl->ops->warm_reset(actrl);
  36}
  37
  38static void compat_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
  39                              unsigned short val)
  40{
  41        struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
  42        struct ac97_controller *actrl = adev->ac97_ctrl;
  43
  44        actrl->ops->write(actrl, ac97->num, reg, val);
  45}
  46
  47static unsigned short compat_ac97_read(struct snd_ac97 *ac97,
  48                                       unsigned short reg)
  49{
  50        struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
  51        struct ac97_controller *actrl = adev->ac97_ctrl;
  52
  53        return actrl->ops->read(actrl, ac97->num, reg);
  54}
  55
  56static const struct snd_ac97_bus_ops compat_snd_ac97_bus_ops = {
  57        .reset = compat_ac97_reset,
  58        .warm_reset = compat_ac97_warm_reset,
  59        .write = compat_ac97_write,
  60        .read = compat_ac97_read,
  61};
  62
  63static struct snd_ac97_bus compat_soc_ac97_bus = {
  64        .ops = &compat_snd_ac97_bus_ops,
  65};
  66
  67struct snd_ac97 *snd_ac97_compat_alloc(struct ac97_codec_device *adev)
  68{
  69        struct snd_ac97 *ac97;
  70        int ret;
  71
  72        ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
  73        if (ac97 == NULL)
  74                return ERR_PTR(-ENOMEM);
  75
  76        ac97->private_data = adev;
  77        ac97->bus = &compat_soc_ac97_bus;
  78
  79        ac97->dev.parent = &adev->dev;
  80        ac97->dev.release = compat_ac97_release;
  81        dev_set_name(&ac97->dev, "%s-compat", dev_name(&adev->dev));
  82        ret = device_register(&ac97->dev);
  83        if (ret) {
  84                put_device(&ac97->dev);
  85                return ERR_PTR(ret);
  86        }
  87
  88        return ac97;
  89}
  90EXPORT_SYMBOL_GPL(snd_ac97_compat_alloc);
  91
  92void snd_ac97_compat_release(struct snd_ac97 *ac97)
  93{
  94        device_unregister(&ac97->dev);
  95}
  96EXPORT_SYMBOL_GPL(snd_ac97_compat_release);
  97
  98int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,
  99        unsigned int id_mask)
 100{
 101        struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
 102        struct ac97_controller *actrl = adev->ac97_ctrl;
 103        unsigned int scanned;
 104
 105        if (try_warm) {
 106                compat_ac97_warm_reset(ac97);
 107                scanned = snd_ac97_bus_scan_one(actrl, adev->num);
 108                if (ac97_ids_match(scanned, adev->vendor_id, id_mask))
 109                        return 1;
 110        }
 111
 112        compat_ac97_reset(ac97);
 113        compat_ac97_warm_reset(ac97);
 114        scanned = snd_ac97_bus_scan_one(actrl, adev->num);
 115        if (ac97_ids_match(scanned, adev->vendor_id, id_mask))
 116                return 0;
 117
 118        return -ENODEV;
 119}
 120EXPORT_SYMBOL_GPL(snd_ac97_reset);
 121