diff options
author | Mark Brown <broonie@kernel.org> | 2018-08-01 10:32:05 +0100 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-08-01 10:32:05 +0100 |
commit | a0b5031582c38f6e2685f7ab9bb0a4168e2a5d1b (patch) | |
tree | 371e79c07ec8700c378b8bd855fcd12a447c6e87 /sound | |
parent | c8cb5f775c8dacb605e628a320ded42be3bd9453 (diff) | |
parent | a57942bfdd61b46df94021c9c33b8faaae5b65e1 (diff) |
Merge branch 'topic/drm_audio_component' of https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound into asoc-4.19
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/seq/seq_clientmgr.c | 3 | ||||
-rw-r--r-- | sound/core/timer.c | 2 | ||||
-rw-r--r-- | sound/hda/Kconfig | 7 | ||||
-rw-r--r-- | sound/hda/Makefile | 1 | ||||
-rw-r--r-- | sound/hda/ext/hdac_ext_bus.c | 80 | ||||
-rw-r--r-- | sound/hda/ext/hdac_ext_controller.c | 64 | ||||
-rw-r--r-- | sound/hda/ext/hdac_ext_stream.c | 104 | ||||
-rw-r--r-- | sound/hda/hdac_component.c | 335 | ||||
-rw-r--r-- | sound/hda/hdac_i915.c | 335 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 73 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 67 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 81 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 24 | ||||
-rw-r--r-- | sound/pci/lx6464es/lx6464es.c | 1 | ||||
-rw-r--r-- | sound/soc/codecs/hdac_hdmi.c | 426 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-messages.c | 50 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-nhlt.c | 8 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-pcm.c | 112 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-topology.c | 20 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-topology.h | 6 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl.c | 190 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl.h | 7 |
23 files changed, 1024 insertions, 975 deletions
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 61a07fe34cd2..56ca78423040 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -2004,7 +2004,8 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client, struct snd_seq_client *cptr = NULL; /* search for next client */ - info->client++; + if (info->client < INT_MAX) + info->client++; if (info->client < 0) info->client = 0; for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) { diff --git a/sound/core/timer.c b/sound/core/timer.c index 665089c45560..b6f076bbc72d 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1520,7 +1520,7 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid) } else { if (id.subdevice < 0) id.subdevice = 0; - else + else if (id.subdevice < INT_MAX) id.subdevice++; } } diff --git a/sound/hda/Kconfig b/sound/hda/Kconfig index 3129546398d0..2d90e11b3eaa 100644 --- a/sound/hda/Kconfig +++ b/sound/hda/Kconfig @@ -5,11 +5,12 @@ config SND_HDA_CORE config SND_HDA_DSP_LOADER bool +config SND_HDA_COMPONENT + bool + config SND_HDA_I915 bool - default y - depends on DRM_I915 - depends on SND_HDA_CORE + select SND_HDA_COMPONENT config SND_HDA_EXT_CORE tristate diff --git a/sound/hda/Makefile b/sound/hda/Makefile index e4e726f2ce98..2160202e2dc1 100644 --- a/sound/hda/Makefile +++ b/sound/hda/Makefile @@ -6,6 +6,7 @@ snd-hda-core-objs += trace.o CFLAGS_trace.o := -I$(src) # for sync with i915 gfx driver +snd-hda-core-$(CONFIG_SND_HDA_COMPONENT) += hdac_component.o snd-hda-core-$(CONFIG_SND_HDA_I915) += hdac_i915.o obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 0daf31383084..9c37d9af3023 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -87,9 +87,10 @@ static const struct hdac_io_ops hdac_ext_default_io = { * * Returns 0 if successful, or a negative error code. */ -int snd_hdac_ext_bus_init(struct hdac_ext_bus *ebus, struct device *dev, +int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, const struct hdac_bus_ops *ops, - const struct hdac_io_ops *io_ops) + const struct hdac_io_ops *io_ops, + const struct hdac_ext_bus_ops *ext_ops) { int ret; static int idx; @@ -98,15 +99,16 @@ int snd_hdac_ext_bus_init(struct hdac_ext_bus *ebus, struct device *dev, if (io_ops == NULL) io_ops = &hdac_ext_default_io; - ret = snd_hdac_bus_init(&ebus->bus, dev, ops, io_ops); + ret = snd_hdac_bus_init(bus, dev, ops, io_ops); if (ret < 0) return ret; - INIT_LIST_HEAD(&ebus->hlink_list); - ebus->idx = idx++; + bus->ext_ops = ext_ops; + INIT_LIST_HEAD(&bus->hlink_list); + bus->idx = idx++; - mutex_init(&ebus->lock); - ebus->cmd_dma_state = true; + mutex_init(&bus->lock); + bus->cmd_dma_state = true; return 0; } @@ -116,10 +118,10 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_init); * snd_hdac_ext_bus_exit - clean up a HD-audio extended bus * @ebus: the pointer to extended bus object */ -void snd_hdac_ext_bus_exit(struct hdac_ext_bus *ebus) +void snd_hdac_ext_bus_exit(struct hdac_bus *bus) { - snd_hdac_bus_exit(&ebus->bus); - WARN_ON(!list_empty(&ebus->hlink_list)); + snd_hdac_bus_exit(bus); + WARN_ON(!list_empty(&bus->hlink_list)); } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_exit); @@ -135,21 +137,15 @@ static void default_release(struct device *dev) * * Returns zero for success or a negative error code. */ -int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *ebus, int addr) +int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr, + struct hdac_device *hdev) { - struct hdac_ext_device *edev; - struct hdac_device *hdev = NULL; - struct hdac_bus *bus = ebus_to_hbus(ebus); char name[15]; int ret; - edev = kzalloc(sizeof(*edev), GFP_KERNEL); - if (!edev) - return -ENOMEM; - hdev = &edev->hdev; - edev->ebus = ebus; + hdev->bus = bus; - snprintf(name, sizeof(name), "ehdaudio%dD%d", ebus->idx, addr); + snprintf(name, sizeof(name), "ehdaudio%dD%d", bus->idx, addr); ret = snd_hdac_device_init(hdev, bus, name, addr); if (ret < 0) { @@ -176,10 +172,8 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init); */ void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev) { - struct hdac_ext_device *edev = to_ehdac_device(hdev); - snd_hdac_device_exit(hdev); - kfree(edev); + kfree(hdev); } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit); @@ -188,14 +182,14 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit); * * @ebus: HD-audio extended bus */ -void snd_hdac_ext_bus_device_remove(struct hdac_ext_bus *ebus) +void snd_hdac_ext_bus_device_remove(struct hdac_bus *bus) { struct hdac_device *codec, *__codec; /* * we need to remove all the codec devices objects created in the * snd_hdac_ext_bus_device_init */ - list_for_each_entry_safe(codec, __codec, &ebus->bus.codec_list, list) { + list_for_each_entry_safe(codec, __codec, &bus->codec_list, list) { snd_hdac_device_unregister(codec); put_device(&codec->dev); } @@ -204,35 +198,31 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_remove); #define dev_to_hdac(dev) (container_of((dev), \ struct hdac_device, dev)) -static inline struct hdac_ext_driver *get_edrv(struct device *dev) +static inline struct hdac_driver *get_hdrv(struct device *dev) { struct hdac_driver *hdrv = drv_to_hdac_driver(dev->driver); - struct hdac_ext_driver *edrv = to_ehdac_driver(hdrv); - - return edrv; + return hdrv; } -static inline struct hdac_ext_device *get_edev(struct device *dev) +static inline struct hdac_device *get_hdev(struct device *dev) { struct hdac_device *hdev = dev_to_hdac_dev(dev); - struct hdac_ext_device *edev = to_ehdac_device(hdev); - - return edev; + return hdev; } static int hda_ext_drv_probe(struct device *dev) { - return (get_edrv(dev))->probe(get_edev(dev)); + return (get_hdrv(dev))->probe(get_hdev(dev)); } static int hdac_ext_drv_remove(struct device *dev) { - return (get_edrv(dev))->remove(get_edev(dev)); + return (get_hdrv(dev))->remove(get_hdev(dev)); } static void hdac_ext_drv_shutdown(struct device *dev) { - return (get_edrv(dev))->shutdown(get_edev(dev)); + return (get_hdrv(dev))->shutdown(get_hdev(dev)); } /** @@ -240,20 +230,20 @@ static void hdac_ext_drv_shutdown(struct device *dev) * * @drv: ext hda driver structure */ -int snd_hda_ext_driver_register(struct hdac_ext_driver *drv) +int snd_hda_ext_driver_register(struct hdac_driver *drv) { - drv->hdac.type = HDA_DEV_ASOC; - drv->hdac.driver.bus = &snd_hda_bus_type; + drv->type = HDA_DEV_ASOC; + drv->driver.bus = &snd_hda_bus_type; /* we use default match */ if (drv->probe) - drv->hdac.driver.probe = hda_ext_drv_probe; + drv->driver.probe = hda_ext_drv_probe; if (drv->remove) - drv->hdac.driver.remove = hdac_ext_drv_remove; + drv->driver.remove = hdac_ext_drv_remove; if (drv->shutdown) - drv->hdac.driver.shutdown = hdac_ext_drv_shutdown; + drv->driver.shutdown = hdac_ext_drv_shutdown; - return driver_register(&drv->hdac.driver); + return driver_register(&drv->driver); } EXPORT_SYMBOL_GPL(snd_hda_ext_driver_register); @@ -262,8 +252,8 @@ EXPORT_SYMBOL_GPL(snd_hda_ext_driver_register); * * @drv: ext hda driver structure */ -void snd_hda_ext_driver_unregister(struct hdac_ext_driver *drv) +void snd_hda_ext_driver_unregister(struct hdac_driver *drv) { - driver_unregister(&drv->hdac.driver); + driver_unregister(&drv->driver); } EXPORT_SYMBOL_GPL(snd_hda_ext_driver_unregister); diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index 84f3b8168716..5bc4a1d587d4 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -39,9 +39,8 @@ * @ebus: HD-audio extended core bus * @enable: flag to turn on/off the capability */ -void snd_hdac_ext_bus_ppcap_enable(struct hdac_ext_bus *ebus, bool enable) +void snd_hdac_ext_bus_ppcap_enable(struct hdac_bus *bus, bool enable) { - struct hdac_bus *bus = &ebus->bus; if (!bus->ppcap) { dev_err(bus->dev, "Address of PP capability is NULL"); @@ -60,9 +59,8 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_enable); * @ebus: HD-audio extended core bus * @enable: flag to enable/disable interrupt */ -void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_ext_bus *ebus, bool enable) +void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_bus *bus, bool enable) { - struct hdac_bus *bus = &ebus->bus; if (!bus->ppcap) { dev_err(bus->dev, "Address of PP capability is NULL\n"); @@ -89,12 +87,11 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_int_enable); * in hlink_list of extended hdac bus * Note: this will be freed on bus exit by driver */ -int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *ebus) +int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_bus *bus) { int idx; u32 link_count; struct hdac_ext_link *hlink; - struct hdac_bus *bus = &ebus->bus; link_count = readl(bus->mlcap + AZX_REG_ML_MLCD) + 1; @@ -114,7 +111,7 @@ int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *ebus) /* since link in On, update the ref */ hlink->ref_count = 1; - list_add_tail(&hlink->list, &ebus->hlink_list); + list_add_tail(&hlink->list, &bus->hlink_list); } return 0; @@ -127,12 +124,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_get_ml_capabilities); * @ebus: HD-audio ext core bus */ -void snd_hdac_link_free_all(struct hdac_ext_bus *ebus) +void snd_hdac_link_free_all(struct hdac_bus *bus) { struct hdac_ext_link *l; - while (!list_empty(&ebus->hlink_list)) { - l = list_first_entry(&ebus->hlink_list, struct hdac_ext_link, list); + while (!list_empty(&bus->hlink_list)) { + l = list_first_entry(&bus->hlink_list, struct hdac_ext_link, list); list_del(&l->list); kfree(l); } @@ -144,7 +141,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_link_free_all); * @ebus: HD-audio extended core bus * @codec_name: codec name */ -struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_ext_bus *ebus, +struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_bus *bus, const char *codec_name) { int i; @@ -153,10 +150,10 @@ struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_ext_bus *ebus, if (sscanf(codec_name, "ehdaudio%dD%d", &bus_idx, &addr) != 2) return NULL; - if (ebus->idx != bus_idx) + if (bus->idx != bus_idx) return NULL; - list_for_each_entry(hlink, &ebus->hlink_list, list) { + list_for_each_entry(hlink, &bus->hlink_list, list) { for (i = 0; i < HDA_MAX_CODECS; i++) { if (hlink->lsdiid & (0x1 << addr)) return hlink; @@ -219,12 +216,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down); * snd_hdac_ext_bus_link_power_up_all -power up all hda link * @ebus: HD-audio extended bus */ -int snd_hdac_ext_bus_link_power_up_all(struct hdac_ext_bus *ebus) +int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus) { struct hdac_ext_link *hlink = NULL; int ret; - list_for_each_entry(hlink, &ebus->hlink_list, list) { + list_for_each_entry(hlink, &bus->hlink_list, list) { snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, 0, AZX_MLCTL_SPA); ret = check_hdac_link_power_active(hlink, true); @@ -240,12 +237,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_up_all); * snd_hdac_ext_bus_link_power_down_all -power down all hda link * @ebus: HD-audio extended bus */ -int snd_hdac_ext_bus_link_power_down_all(struct hdac_ext_bus *ebus) +int snd_hdac_ext_bus_link_power_down_all(struct hdac_bus *bus) { struct hdac_ext_link *hlink = NULL; int ret; - list_for_each_entry(hlink, &ebus->hlink_list, list) { + list_for_each_entry(hlink, &bus->hlink_list, list) { snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, AZX_MLCTL_SPA, 0); ret = check_hdac_link_power_active(hlink, false); if (ret < 0) @@ -256,39 +253,48 @@ int snd_hdac_ext_bus_link_power_down_all(struct hdac_ext_bus *ebus) } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down_all); -int snd_hdac_ext_bus_link_get(struct hdac_ext_bus *ebus, +int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *link) { int ret = 0; - mutex_lock(&ebus->lock); + mutex_lock(&bus->lock); /* * if we move from 0 to 1, count will be 1 so power up this link * as well, also check the dma status and trigger that */ if (++link->ref_count == 1) { - if (!ebus->cmd_dma_state) { - snd_hdac_bus_init_cmd_io(&ebus->bus); - ebus->cmd_dma_state = true; + if (!bus->cmd_dma_state) { + snd_hdac_bus_init_cmd_io(bus); + bus->cmd_dma_state = true; } ret = snd_hdac_ext_bus_link_power_up(link); + + /* + * wait for 521usec for codec to report status + * HDA spec section 4.3 - Codec Discovery + */ + udelay(521); + bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS); + dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask); + snd_hdac_chip_writew(bus, STATESTS, bus->codec_mask); } - mutex_unlock(&ebus->lock); + mutex_unlock(&bus->lock); return ret; } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_get); -int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus, +int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *link) { int ret = 0; struct hdac_ext_link *hlink; bool link_up = false; - mutex_lock(&ebus->lock); + mutex_lock(&bus->lock); /* * if we move from 1 to 0, count will be 0 @@ -301,7 +307,7 @@ int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus, * now check if all links are off, if so turn off * cmd dma as well */ - list_for_each_entry(hlink, &ebus->hlink_list, list) { + list_for_each_entry(hlink, &bus->hlink_list, list) { if (hlink->ref_count) { link_up = true; break; @@ -309,12 +315,12 @@ int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus, } if (!link_up) { - snd_hdac_bus_stop_cmd_io(&ebus->bus); - ebus->cmd_dma_state = false; + snd_hdac_bus_stop_cmd_io(bus); + bus->cmd_dma_state = false; } } - mutex_unlock(&ebus->lock); + mutex_unlock(&bus->lock); return ret; } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_put); diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index c96d7a7a36af..1bd27576db98 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -25,7 +25,7 @@ /** * snd_hdac_ext_stream_init - initialize each stream (aka device) - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @stream: HD-audio ext core stream object to initialize * @idx: stream index number * @direction: stream direction (SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE) @@ -34,18 +34,16 @@ * initialize the stream, if ppcap is enabled then init those and then * invoke hdac stream initialization routine */ -void snd_hdac_ext_stream_init(struct hdac_ext_bus *ebus, +void snd_hdac_ext_stream_init(struct hdac_bus *bus, struct hdac_ext_stream *stream, int idx, int direction, int tag) { - struct hdac_bus *bus = &ebus->bus; - if (bus->ppcap) { stream->pphc_addr = bus->ppcap + AZX_PPHC_BASE + AZX_PPHC_INTERVAL * idx; stream->pplc_addr = bus->ppcap + AZX_PPLC_BASE + - AZX_PPLC_MULTI * ebus->num_streams + + AZX_PPLC_MULTI * bus->num_streams + AZX_PPLC_INTERVAL * idx; } @@ -71,12 +69,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init); /** * snd_hdac_ext_stream_init_all - create and initialize the stream objects * for an extended hda bus - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @start_idx: start index for streams * @num_stream: number of streams to initialize * @dir: direction of streams */ -int snd_hdac_ext_stream_init_all(struct hdac_ext_bus *ebus, int start_idx, +int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, int num_stream, int dir) { int stream_tag = 0; @@ -88,7 +86,7 @@ int snd_hdac_ext_stream_init_all(struct hdac_ext_bus *ebus, int start_idx, if (!stream) return -ENOMEM; tag = ++stream_tag; - snd_hdac_ext_stream_init(ebus, stream, idx, dir, tag); + snd_hdac_ext_stream_init(bus, stream, idx, dir, tag); idx++; } @@ -100,17 +98,16 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init_all); /** * snd_hdac_stream_free_all - free hdac extended stream objects * - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus */ -void snd_hdac_stream_free_all(struct hdac_ext_bus *ebus) +void snd_hdac_stream_free_all(struct hdac_bus *bus) { struct hdac_stream *s, *_s; struct hdac_ext_stream *stream; - struct hdac_bus *bus = ebus_to_hbus(ebus); list_for_each_entry_safe(s, _s, &bus->stream_list, list) { stream = stream_to_hdac_ext_stream(s); - snd_hdac_ext_stream_decouple(ebus, stream, false); + snd_hdac_ext_stream_decouple(bus, stream, false); list_del(&s->list); kfree(stream); } @@ -119,15 +116,14 @@ EXPORT_SYMBOL_GPL(snd_hdac_stream_free_all); /** * snd_hdac_ext_stream_decouple - decouple the hdac stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @stream: HD-audio ext core stream object to initialize * @decouple: flag to decouple */ -void snd_hdac_ext_stream_decouple(struct hdac_ext_bus *ebus, +void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, struct hdac_ext_stream *stream, bool decouple) { struct hdac_stream *hstream = &stream->hstream; - struct hdac_bus *bus = &ebus->bus; u32 val; int mask = AZX_PPCTL_PROCEN(hstream->index); @@ -251,19 +247,18 @@ void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link, EXPORT_SYMBOL_GPL(snd_hdac_ext_link_clear_stream_id); static struct hdac_ext_stream * -hdac_ext_link_stream_assign(struct hdac_ext_bus *ebus, +hdac_ext_link_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream) { struct hdac_ext_stream *res = NULL; struct hdac_stream *stream = NULL; - struct hdac_bus *hbus = &ebus->bus; - if (!hbus->ppcap) { - dev_err(hbus->dev, "stream type not supported\n"); + if (!bus->ppcap) { + dev_err(bus->dev, "stream type not supported\n"); return NULL; } - list_for_each_entry(stream, &hbus->stream_list, list) { + list_for_each_entry(stream, &bus->stream_list, list) { struct hdac_ext_stream *hstream = container_of(stream, struct hdac_ext_stream, hstream); @@ -277,34 +272,33 @@ hdac_ext_link_stream_assign(struct hdac_ext_bus *ebus, } if (!hstream->link_locked) { - snd_hdac_ext_stream_decouple(ebus, hstream, true); + snd_hdac_ext_stream_decouple(bus, hstream, true); res = hstream; break; } } if (res) { - spin_lock_irq(&hbus->reg_lock); + spin_lock_irq(&bus->reg_lock); res->link_locked = 1; res->link_substream = substream; - spin_unlock_irq(&hbus->reg_lock); + spin_unlock_irq(&bus->reg_lock); } return res; } static struct hdac_ext_stream * -hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus, +hdac_ext_host_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream) { struct hdac_ext_stream *res = NULL; struct hdac_stream *stream = NULL; - struct hdac_bus *hbus = &ebus->bus; - if (!hbus->ppcap) { - dev_err(hbus->dev, "stream type not supported\n"); + if (!bus->ppcap) { + dev_err(bus->dev, "stream type not supported\n"); return NULL; } - list_for_each_entry(stream, &hbus->stream_list, list) { + list_for_each_entry(stream, &bus->stream_list, list) { struct hdac_ext_stream *hstream = container_of(stream, struct hdac_ext_stream, hstream); @@ -313,17 +307,17 @@ hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus, if (!stream->opened) { if (!hstream->decoupled) - snd_hdac_ext_stream_decouple(ebus, hstream, true); + snd_hdac_ext_stream_decouple(bus, hstream, true); res = hstream; break; } } if (res) { - spin_lock_irq(&hbus->reg_lock); + spin_lock_irq(&bus->reg_lock); res->hstream.opened = 1; res->hstream.running = 0; res->hstream.substream = substream; - spin_unlock_irq(&hbus->reg_lock); + spin_unlock_irq(&bus->reg_lock); } return res; @@ -331,7 +325,7 @@ hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus, /** * snd_hdac_ext_stream_assign - assign a stream for the PCM - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @substream: PCM substream to assign * @type: type of stream (coupled, host or link stream) * @@ -346,27 +340,26 @@ hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus, * the same stream object when it's used beforehand. when a stream is * decoupled, it becomes a host stream and link stream. */ -struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_ext_bus *ebus, +struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream, int type) { struct hdac_ext_stream *hstream = NULL; struct hdac_stream *stream = NULL; - struct hdac_bus *hbus = &ebus->bus; switch (type) { case HDAC_EXT_STREAM_TYPE_COUPLED: - stream = snd_hdac_stream_assign(hbus, substream); + stream = snd_hdac_stream_assign(bus, substream); if (stream) hstream = container_of(stream, struct hdac_ext_stream, hstream); return hstream; case HDAC_EXT_STREAM_TYPE_HOST: - return hdac_ext_host_stream_assign(ebus, substream); + return hdac_ext_host_stream_assign(bus, substream); case HDAC_EXT_STREAM_TYPE_LINK: - return hdac_ext_link_stream_assign(ebus, substream); + return hdac_ext_link_stream_assign(bus, substream); default: return NULL; @@ -384,7 +377,6 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_assign); void snd_hdac_ext_stream_release(struct hdac_ext_stream *stream, int type) { struct hdac_bus *bus = stream->hstream.bus; - struct hdac_ext_bus *ebus = hbus_to_ebus(bus); switch (type) { case HDAC_EXT_STREAM_TYPE_COUPLED: @@ -393,13 +385,13 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *stream, int type) case HDAC_EXT_STREAM_TYPE_HOST: if (stream->decoupled && !stream->link_locked) - snd_hdac_ext_stream_decouple(ebus, stream, false); + snd_hdac_ext_stream_decouple(bus, stream, false); snd_hdac_stream_release(&stream->hstream); break; case HDAC_EXT_STREAM_TYPE_LINK: if (stream->decoupled && !stream->hstream.opened) - snd_hdac_ext_stream_decouple(ebus, stream, false); + snd_hdac_ext_stream_decouple(bus, stream, false); spin_lock_irq(&bus->reg_lock); stream->link_locked = 0; stream->link_substream = NULL; @@ -415,16 +407,15 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_release); /** * snd_hdac_ext_stream_spbcap_enable - enable SPIB for a stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @enable: flag to enable/disable SPIB * @index: stream index for which SPIB need to be enabled */ -void snd_hdac_ext_stream_spbcap_enable(struct hdac_ext_bus *ebus, +void snd_hdac_ext_stream_spbcap_enable(struct hdac_bus *bus, bool enable, int index) { u32 mask = 0; u32 register_mask = 0; - struct hdac_bus *bus = &ebus->bus; if (!bus->spbcap) { dev_err(bus->dev, "Address of SPB capability is NULL\n"); @@ -446,14 +437,13 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_spbcap_enable); /** * snd_hdac_ext_stream_set_spib - sets the spib value of a stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @stream: hdac_ext_stream * @value: spib value to set */ -int snd_hdac_ext_stream_set_spib(struct hdac_ext_bus *ebus, +int snd_hdac_ext_stream_set_spib(struct hdac_bus *bus, struct hdac_ext_stream *stream, u32 value) { - struct hdac_bus *bus = &ebus->bus; if (!bus->spbcap) { dev_err(bus->dev, "Address of SPB capability is NULL\n"); @@ -468,15 +458,14 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_spib); /** * snd_hdac_ext_stream_get_spbmaxfifo - gets the spib value of a stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @stream: hdac_ext_stream * * Return maxfifo for the stream */ -int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_ext_bus *ebus, +int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_bus *bus, struct hdac_ext_stream *stream) { - struct hdac_bus *bus = &ebus->bus; if (!bus->spbcap) { dev_err(bus->dev, "Address of SPB capability is NULL\n"); @@ -490,11 +479,10 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_get_spbmaxfifo); /** * snd_hdac_ext_stop_streams - stop all stream if running - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus */ -void snd_hdac_ext_stop_streams(struct hdac_ext_bus *ebus) +void snd_hdac_ext_stop_streams(struct hdac_bus *bus) { - struct hdac_bus *bus = ebus_to_hbus(ebus); struct hdac_stream *stream; if (bus->chip_init) { @@ -507,16 +495,15 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stop_streams); /** * snd_hdac_ext_stream_drsm_enable - enable DMA resume for a stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @enable: flag to enable/disable DRSM * @index: stream index for which DRSM need to be enabled */ -void snd_hdac_ext_stream_drsm_enable(struct hdac_ext_bus *ebus, +void snd_hdac_ext_stream_drsm_enable(struct hdac_bus *bus, bool enable, int index) { u32 mask = 0; u32 register_mask = 0; - struct hdac_bus *bus = &ebus->bus; if (!bus->drsmcap) { dev_err(bus->dev, "Address of DRSM capability is NULL\n"); @@ -538,14 +525,13 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_drsm_enable); /** * snd_hdac_ext_stream_set_dpibr - sets the dpibr value of a stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @stream: hdac_ext_stream * @value: dpib value to set */ -int snd_hdac_ext_stream_set_dpibr(struct hdac_ext_bus *ebus, +int snd_hdac_ext_stream_set_dpibr(struct hdac_bus *bus, struct hdac_ext_stream *stream, u32 value) { - struct hdac_bus *bus = &ebus->bus; if (!bus->drsmcap) { dev_err(bus->dev, "Address of DRSM capability is NULL\n"); @@ -560,7 +546,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_dpibr); /** * snd_hdac_ext_stream_set_lpib - sets the lpib value of a stream - * @ebus: HD-audio ext core bus + * @bus: HD-audio core bus * @stream: hdac_ext_stream * @value: lpib value to set */ diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c new file mode 100644 index 000000000000..6e46a9c73aed --- /dev/null +++ b/sound/hda/hdac_component.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0 +// hdac_component.c - routines for sync between HD-A core and DRM driver + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/component.h> +#include <sound/core.h> +#include <sound/hdaudio.h> +#include <sound/hda_component.h> +#include <sound/hda_register.h> + +static void hdac_acomp_release(struct device *dev, void *res) +{ +} + +static struct drm_audio_component *hdac_get_acomp(struct device *dev) +{ + return devres_find(dev, hdac_acomp_release, NULL, NULL); +} + +/** + * snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup + * @bus: HDA core bus + * @enable: enable or disable the wakeup + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function should be called during the chip reset, also called at + * resume for updating STATESTS register read. + * + * Returns zero for success or a negative error code. + */ +int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) +{ + struct drm_audio_component *acomp = bus->audio_component; + + if (!acomp || !acomp->ops) + return -ENODEV; + + if (!acomp->ops->codec_wake_override) + return 0; + + dev_dbg(bus->dev, "%s codec wakeup\n", + enable ? "enable" : "disable"); + + acomp->ops->codec_wake_override(acomp->dev, enable); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup); + +/** + * snd_hdac_display_power - Power up / down the power refcount + * @bus: HDA core bus + * @enable: power up or down + * + * This function is supposed to be used only by a HD-audio controller + * driver that needs the interaction with graphics driver. + * + * This function manages a refcount and calls the get_power() and + * put_power() ops accordingly, toggling the codec wakeup, too. + * + * Returns zero for success or a negative error code. + */ +int snd_hdac_display_power(struct hdac_bus *bus, bool enable) +{ + struct drm_audio_component *acomp = bus->audio_component; + + if (!acom |