1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
274426fbfSRobert Jarzmik /*
374426fbfSRobert Jarzmik * Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr>
474426fbfSRobert Jarzmik */
574426fbfSRobert Jarzmik
674426fbfSRobert Jarzmik #include <linux/list.h>
774426fbfSRobert Jarzmik #include <linux/slab.h>
874426fbfSRobert Jarzmik #include <sound/ac97/codec.h>
974426fbfSRobert Jarzmik #include <sound/ac97/compat.h>
1074426fbfSRobert Jarzmik #include <sound/ac97/controller.h>
1174426fbfSRobert Jarzmik #include <sound/soc.h>
1274426fbfSRobert Jarzmik
1374426fbfSRobert Jarzmik #include "ac97_core.h"
1474426fbfSRobert Jarzmik
compat_ac97_release(struct device * dev)15c7b81707SLihua Yao static void compat_ac97_release(struct device *dev)
16c7b81707SLihua Yao {
17c7b81707SLihua Yao kfree(to_ac97_t(dev));
18c7b81707SLihua Yao }
19c7b81707SLihua Yao
compat_ac97_reset(struct snd_ac97 * ac97)2074426fbfSRobert Jarzmik static void compat_ac97_reset(struct snd_ac97 *ac97)
2174426fbfSRobert Jarzmik {
2274426fbfSRobert Jarzmik struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
2374426fbfSRobert Jarzmik struct ac97_controller *actrl = adev->ac97_ctrl;
2474426fbfSRobert Jarzmik
2574426fbfSRobert Jarzmik if (actrl->ops->reset)
2674426fbfSRobert Jarzmik actrl->ops->reset(actrl);
2774426fbfSRobert Jarzmik }
2874426fbfSRobert Jarzmik
compat_ac97_warm_reset(struct snd_ac97 * ac97)2974426fbfSRobert Jarzmik static void compat_ac97_warm_reset(struct snd_ac97 *ac97)
3074426fbfSRobert Jarzmik {
3174426fbfSRobert Jarzmik struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
3274426fbfSRobert Jarzmik struct ac97_controller *actrl = adev->ac97_ctrl;
3374426fbfSRobert Jarzmik
3474426fbfSRobert Jarzmik if (actrl->ops->warm_reset)
3574426fbfSRobert Jarzmik actrl->ops->warm_reset(actrl);
3674426fbfSRobert Jarzmik }
3774426fbfSRobert Jarzmik
compat_ac97_write(struct snd_ac97 * ac97,unsigned short reg,unsigned short val)3874426fbfSRobert Jarzmik static void compat_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
3974426fbfSRobert Jarzmik unsigned short val)
4074426fbfSRobert Jarzmik {
4174426fbfSRobert Jarzmik struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
4274426fbfSRobert Jarzmik struct ac97_controller *actrl = adev->ac97_ctrl;
4374426fbfSRobert Jarzmik
4474426fbfSRobert Jarzmik actrl->ops->write(actrl, ac97->num, reg, val);
4574426fbfSRobert Jarzmik }
4674426fbfSRobert Jarzmik
compat_ac97_read(struct snd_ac97 * ac97,unsigned short reg)4774426fbfSRobert Jarzmik static unsigned short compat_ac97_read(struct snd_ac97 *ac97,
4874426fbfSRobert Jarzmik unsigned short reg)
4974426fbfSRobert Jarzmik {
5074426fbfSRobert Jarzmik struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
5174426fbfSRobert Jarzmik struct ac97_controller *actrl = adev->ac97_ctrl;
5274426fbfSRobert Jarzmik
5374426fbfSRobert Jarzmik return actrl->ops->read(actrl, ac97->num, reg);
5474426fbfSRobert Jarzmik }
5574426fbfSRobert Jarzmik
56*33c83aafSTakashi Iwai static const struct snd_ac97_bus_ops compat_snd_ac97_bus_ops = {
5774426fbfSRobert Jarzmik .reset = compat_ac97_reset,
5874426fbfSRobert Jarzmik .warm_reset = compat_ac97_warm_reset,
5974426fbfSRobert Jarzmik .write = compat_ac97_write,
6074426fbfSRobert Jarzmik .read = compat_ac97_read,
6174426fbfSRobert Jarzmik };
6274426fbfSRobert Jarzmik
6374426fbfSRobert Jarzmik static struct snd_ac97_bus compat_soc_ac97_bus = {
6474426fbfSRobert Jarzmik .ops = &compat_snd_ac97_bus_ops,
6574426fbfSRobert Jarzmik };
6674426fbfSRobert Jarzmik
snd_ac97_compat_alloc(struct ac97_codec_device * adev)6774426fbfSRobert Jarzmik struct snd_ac97 *snd_ac97_compat_alloc(struct ac97_codec_device *adev)
6874426fbfSRobert Jarzmik {
6974426fbfSRobert Jarzmik struct snd_ac97 *ac97;
70c7b81707SLihua Yao int ret;
7174426fbfSRobert Jarzmik
7274426fbfSRobert Jarzmik ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
7374426fbfSRobert Jarzmik if (ac97 == NULL)
7474426fbfSRobert Jarzmik return ERR_PTR(-ENOMEM);
7574426fbfSRobert Jarzmik
7674426fbfSRobert Jarzmik ac97->private_data = adev;
7774426fbfSRobert Jarzmik ac97->bus = &compat_soc_ac97_bus;
78c7b81707SLihua Yao
79c7b81707SLihua Yao ac97->dev.parent = &adev->dev;
80c7b81707SLihua Yao ac97->dev.release = compat_ac97_release;
81c7b81707SLihua Yao dev_set_name(&ac97->dev, "%s-compat", dev_name(&adev->dev));
82c7b81707SLihua Yao ret = device_register(&ac97->dev);
83c7b81707SLihua Yao if (ret) {
84c7b81707SLihua Yao put_device(&ac97->dev);
85c7b81707SLihua Yao return ERR_PTR(ret);
86c7b81707SLihua Yao }
87c7b81707SLihua Yao
8874426fbfSRobert Jarzmik return ac97;
8974426fbfSRobert Jarzmik }
9074426fbfSRobert Jarzmik EXPORT_SYMBOL_GPL(snd_ac97_compat_alloc);
9174426fbfSRobert Jarzmik
snd_ac97_compat_release(struct snd_ac97 * ac97)9274426fbfSRobert Jarzmik void snd_ac97_compat_release(struct snd_ac97 *ac97)
9374426fbfSRobert Jarzmik {
94c7b81707SLihua Yao device_unregister(&ac97->dev);
9574426fbfSRobert Jarzmik }
9674426fbfSRobert Jarzmik EXPORT_SYMBOL_GPL(snd_ac97_compat_release);
9774426fbfSRobert Jarzmik
snd_ac97_reset(struct snd_ac97 * ac97,bool try_warm,unsigned int id,unsigned int id_mask)9874426fbfSRobert Jarzmik int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,
9974426fbfSRobert Jarzmik unsigned int id_mask)
10074426fbfSRobert Jarzmik {
10174426fbfSRobert Jarzmik struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
10274426fbfSRobert Jarzmik struct ac97_controller *actrl = adev->ac97_ctrl;
10374426fbfSRobert Jarzmik unsigned int scanned;
10474426fbfSRobert Jarzmik
10574426fbfSRobert Jarzmik if (try_warm) {
10674426fbfSRobert Jarzmik compat_ac97_warm_reset(ac97);
10774426fbfSRobert Jarzmik scanned = snd_ac97_bus_scan_one(actrl, adev->num);
10874426fbfSRobert Jarzmik if (ac97_ids_match(scanned, adev->vendor_id, id_mask))
10974426fbfSRobert Jarzmik return 1;
11074426fbfSRobert Jarzmik }
11174426fbfSRobert Jarzmik
11274426fbfSRobert Jarzmik compat_ac97_reset(ac97);
11374426fbfSRobert Jarzmik compat_ac97_warm_reset(ac97);
11474426fbfSRobert Jarzmik scanned = snd_ac97_bus_scan_one(actrl, adev->num);
11574426fbfSRobert Jarzmik if (ac97_ids_match(scanned, adev->vendor_id, id_mask))
11674426fbfSRobert Jarzmik return 0;
11774426fbfSRobert Jarzmik
11874426fbfSRobert Jarzmik return -ENODEV;
11974426fbfSRobert Jarzmik }
12074426fbfSRobert Jarzmik EXPORT_SYMBOL_GPL(snd_ac97_reset);
121