Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: hdac_ext: add extended HDA bus

The new HDA controllers from Intel support new capabilities like
multilink, pipe processing, SPIB, GTS etc In order to use them we
create an extended HDA bus which embed the hdac bus and contains the
fields for extended configurations

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Jeeja KP and committed by
Takashi Iwai
dfe66a18 27c41dad

+173
+46
include/sound/hdaudio_ext.h
··· 1 + #ifndef __SOUND_HDAUDIO_EXT_H 2 + #define __SOUND_HDAUDIO_EXT_H 3 + 4 + #include <sound/hdaudio.h> 5 + 6 + /** 7 + * hdac_ext_bus: HDAC extended bus for extended HDA caps 8 + * 9 + * @bus: hdac bus 10 + * @num_streams: streams supported 11 + * @ppcap: pp capabilities pointer 12 + * @spbcap: SPIB capabilities pointer 13 + * @mlcap: MultiLink capabilities pointer 14 + * @gtscap: gts capabilities pointer 15 + * @hlink_list: link list of HDA links 16 + */ 17 + struct hdac_ext_bus { 18 + struct hdac_bus bus; 19 + int num_streams; 20 + int idx; 21 + 22 + void __iomem *ppcap; 23 + void __iomem *spbcap; 24 + void __iomem *mlcap; 25 + void __iomem *gtscap; 26 + 27 + struct list_head hlink_list; 28 + }; 29 + 30 + int snd_hdac_ext_bus_init(struct hdac_ext_bus *sbus, struct device *dev, 31 + const struct hdac_bus_ops *ops, 32 + const struct hdac_io_ops *io_ops); 33 + 34 + void snd_hdac_ext_bus_exit(struct hdac_ext_bus *sbus); 35 + int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *sbus, int addr); 36 + void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev); 37 + 38 + #define ebus_to_hbus(ebus) (&(ebus)->bus) 39 + #define hbus_to_ebus(_bus) \ 40 + container_of(_bus, struct hdac_ext_bus, bus) 41 + 42 + int snd_hdac_ext_bus_parse_capabilities(struct hdac_ext_bus *sbus); 43 + void snd_hdac_ext_bus_ppcap_enable(struct hdac_ext_bus *chip, bool enable); 44 + void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_ext_bus *chip, bool enable); 45 + 46 + #endif /* __SOUND_HDAUDIO_EXT_H */
+4
sound/hda/Kconfig
··· 10 10 default y 11 11 depends on DRM_I915 12 12 depends on SND_HDA_CORE 13 + 14 + config SND_HDA_EXT_CORE 15 + tristate 16 + select SND_HDA_CORE
+3
sound/hda/Makefile
··· 8 8 snd-hda-core-$(CONFIG_SND_HDA_I915) += hdac_i915.o 9 9 10 10 obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o 11 + 12 + #extended hda 13 + obj-$(CONFIG_SND_HDA_EXT_CORE) += ext/
+3
sound/hda/ext/Makefile
··· 1 + snd-hda-ext-core-objs := hdac_ext_bus.o 2 + 3 + obj-$(CONFIG_SND_HDA_EXT_CORE) += snd-hda-ext-core.o
+117
sound/hda/ext/hdac_ext_bus.c
··· 1 + /* 2 + * hdac-ext-bus.c - HD-audio extended core bus functions. 3 + * 4 + * Copyright (C) 2014-2015 Intel Corp 5 + * Author: Jeeja KP <jeeja.kp@intel.com> 6 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; version 2 of the License. 11 + * 12 + * This program is distributed in the hope that it will be useful, but 13 + * WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 + * General Public License for more details. 16 + * 17 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 + */ 19 + 20 + #include <linux/module.h> 21 + #include <linux/slab.h> 22 + #include <sound/hdaudio_ext.h> 23 + 24 + MODULE_DESCRIPTION("HDA extended core"); 25 + MODULE_LICENSE("GPL v2"); 26 + 27 + /** 28 + * snd_hdac_ext_bus_init - initialize a HD-audio extended bus 29 + * @ebus: the pointer to extended bus object 30 + * @dev: device pointer 31 + * @ops: bus verb operators 32 + * @io_ops: lowlevel I/O operators 33 + * 34 + * Returns 0 if successful, or a negative error code. 35 + */ 36 + int snd_hdac_ext_bus_init(struct hdac_ext_bus *ebus, struct device *dev, 37 + const struct hdac_bus_ops *ops, 38 + const struct hdac_io_ops *io_ops) 39 + { 40 + int ret; 41 + static int idx; 42 + 43 + ret = snd_hdac_bus_init(&ebus->bus, dev, ops, io_ops); 44 + if (ret < 0) 45 + return ret; 46 + 47 + INIT_LIST_HEAD(&ebus->hlink_list); 48 + ebus->idx = idx++; 49 + 50 + return 0; 51 + } 52 + EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_init); 53 + 54 + /** 55 + * snd_hdac_ext_bus_exit - clean up a HD-audio extended bus 56 + * @ebus: the pointer to extended bus object 57 + */ 58 + void snd_hdac_ext_bus_exit(struct hdac_ext_bus *ebus) 59 + { 60 + snd_hdac_bus_exit(&ebus->bus); 61 + WARN_ON(!list_empty(&ebus->hlink_list)); 62 + } 63 + EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_exit); 64 + 65 + static void default_release(struct device *dev) 66 + { 67 + snd_hdac_ext_bus_device_exit(container_of(dev, struct hdac_device, dev)); 68 + } 69 + 70 + /** 71 + * snd_hdac_ext_device_init - initialize the HDA extended codec base device 72 + * @ebus: hdac extended bus to attach to 73 + * @addr: codec address 74 + * 75 + * Returns zero for success or a negative error code. 76 + */ 77 + int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *ebus, int addr) 78 + { 79 + struct hdac_device *hdev = NULL; 80 + struct hdac_bus *bus = ebus_to_hbus(ebus); 81 + char name[15]; 82 + int ret; 83 + 84 + hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); 85 + if (!hdev) 86 + return -ENOMEM; 87 + 88 + snprintf(name, sizeof(name), "ehdaudio%dD%d", ebus->idx, addr); 89 + 90 + ret = snd_hdac_device_init(hdev, bus, name, addr); 91 + if (ret < 0) { 92 + dev_err(bus->dev, "device init failed for hdac device\n"); 93 + return ret; 94 + } 95 + hdev->type = HDA_DEV_ASOC; 96 + hdev->dev.release = default_release; 97 + 98 + ret = snd_hdac_device_register(hdev); 99 + if (ret) { 100 + dev_err(bus->dev, "failed to register hdac device\n"); 101 + snd_hdac_ext_bus_device_exit(hdev); 102 + return ret; 103 + } 104 + return 0; 105 + } 106 + EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init); 107 + 108 + /** 109 + * snd_hdac_ext_bus_device_exit - clean up a HD-audio extended codec base device 110 + * @hdev: hdac device to clean up 111 + */ 112 + void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev) 113 + { 114 + snd_hdac_device_exit(hdev); 115 + kfree(hdev); 116 + } 117 + EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit);