From 102a0743326a03cd1a1202ceda21e175b7d3575c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 20 Feb 2024 01:20:52 +0000 Subject: [PATCH] add new system file --- kernel/sound/pci/hda/hda_controller.c | 171 ++++++++++++++------------------------------------------ 1 files changed, 44 insertions(+), 127 deletions(-) diff --git a/kernel/sound/pci/hda/hda_controller.c b/kernel/sound/pci/hda/hda_controller.c index 0c5d41e..ea76395 100644 --- a/kernel/sound/pci/hda/hda_controller.c +++ b/kernel/sound/pci/hda/hda_controller.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * * Implementation of primary alsa driver code base for Intel HD Audio. @@ -6,18 +7,6 @@ * * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de> * PeiSen Hou <pshou@realtek.com.tw> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * */ #include <linux/clocksource.h> @@ -36,6 +25,7 @@ #include <sound/core.h> #include <sound/initval.h> #include "hda_controller.h" +#include "hda_local.h" #define CREATE_TRACE_POINTS #include "hda_controller_trace.h" @@ -118,7 +108,7 @@ struct azx_pcm *apcm = snd_pcm_substream_chip(substream); struct azx *chip = apcm->chip; struct azx_dev *azx_dev = get_azx_dev(substream); - int ret; + int ret = 0; trace_azx_pcm_hw_params(chip, azx_dev); dsp_lock(azx_dev); @@ -130,8 +120,7 @@ azx_dev->core.bufsize = 0; azx_dev->core.period_bytes = 0; azx_dev->core.format_val = 0; - ret = chip->ops->substream_alloc_pages(chip, substream, - params_buffer_bytes(hw_params)); + unlock: dsp_unlock(azx_dev); return ret; @@ -141,9 +130,7 @@ { struct azx_pcm *apcm = snd_pcm_substream_chip(substream); struct azx_dev *azx_dev = get_azx_dev(substream); - struct azx *chip = apcm->chip; struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); - int err; /* reset BDL address */ dsp_lock(azx_dev); @@ -152,10 +139,9 @@ snd_hda_codec_cleanup(apcm->codec, hinfo, substream); - err = chip->ops->substream_free_pages(chip, substream); azx_stream(azx_dev)->prepared = 0; dsp_unlock(azx_dev); - return err; + return 0; } static int azx_pcm_prepare(struct snd_pcm_substream *substream) @@ -388,7 +374,7 @@ u32 wallclk_ctr, wallclk_cycles; bool direction; u32 dma_select; - u32 timeout = 200; + u32 timeout; u32 retry_count = 0; runtime = substream->runtime; @@ -502,7 +488,7 @@ } static int azx_get_time_info(struct snd_pcm_substream *substream, - struct timespec *system_ts, struct timespec *audio_ts, + struct timespec64 *system_ts, struct timespec64 *audio_ts, struct snd_pcm_audio_tstamp_config *audio_tstamp_config, struct snd_pcm_audio_tstamp_report *audio_tstamp_report) { @@ -522,7 +508,7 @@ if (audio_tstamp_config->report_delay) nsec = azx_adjust_codec_delay(substream, nsec); - *audio_ts = ns_to_timespec(nsec); + *audio_ts = ns_to_timespec64(nsec); audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK; audio_tstamp_report->accuracy_report = 1; /* rest of structure is valid */ @@ -539,16 +525,16 @@ return -EINVAL; case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW: - *system_ts = ktime_to_timespec(xtstamp.sys_monoraw); + *system_ts = ktime_to_timespec64(xtstamp.sys_monoraw); break; default: - *system_ts = ktime_to_timespec(xtstamp.sys_realtime); + *system_ts = ktime_to_timespec64(xtstamp.sys_realtime); break; } - *audio_ts = ktime_to_timespec(xtstamp.device); + *audio_ts = ktime_to_timespec64(xtstamp.device); audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED; @@ -563,7 +549,7 @@ return 0; } -static struct snd_pcm_hardware azx_pcm_hw = { +static const struct snd_pcm_hardware azx_pcm_hw = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -697,7 +683,6 @@ static const struct snd_pcm_ops azx_pcm_ops = { .open = azx_pcm_open, .close = azx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, .hw_params = azx_pcm_hw_params, .hw_free = azx_pcm_hw_free, .prepare = azx_pcm_prepare, @@ -705,7 +690,6 @@ .pointer = azx_pcm_pointer, .get_time_info = azx_get_time_info, .mmap = azx_pcm_mmap, - .page = snd_pcm_sgbuf_ops_page, }; static void azx_pcm_free(struct snd_pcm *pcm) @@ -730,6 +714,7 @@ int pcm_dev = cpcm->device; unsigned int size; int s, err; + int type = SNDRV_DMA_TYPE_DEV_SG; list_for_each_entry(apcm, &chip->pcm_list, list) { if (apcm->pcm->device == pcm_dev) { @@ -768,9 +753,10 @@ size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024; if (size > MAX_PREALLOC_SIZE) size = MAX_PREALLOC_SIZE; - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - chip->card->dev, - size, MAX_PREALLOC_SIZE); + if (chip->uc_buffer) + type = SNDRV_DMA_TYPE_DEV_UC_SG; + snd_pcm_set_managed_buffer_all(pcm, type, chip->card->dev, + size, MAX_PREALLOC_SIZE); return 0; } @@ -792,54 +778,21 @@ { struct azx *chip = bus_to_azx(bus); struct hda_bus *hbus = &chip->bus; - unsigned long timeout; - unsigned long loopcounter; - int do_poll = 0; + int err; again: - timeout = jiffies + msecs_to_jiffies(1000); - - for (loopcounter = 0;; loopcounter++) { - spin_lock_irq(&bus->reg_lock); - if (chip->polling_mode || do_poll) - snd_hdac_bus_update_rirb(bus); - if (!bus->rirb.cmds[addr]) { - if (!do_poll) - chip->poll_count = 0; - if (res) - *res = bus->rirb.res[addr]; /* the last value */ - spin_unlock_irq(&bus->reg_lock); - return 0; - } - spin_unlock_irq(&bus->reg_lock); - if (time_after(jiffies, timeout)) - break; - if (hbus->needs_damn_long_delay || loopcounter > 3000) - msleep(2); /* temporary workaround */ - else { - udelay(10); - cond_resched(); - } - } + err = snd_hdac_bus_get_response(bus, addr, res); + if (!err) + return 0; if (hbus->no_response_fallback) return -EIO; - if (!chip->polling_mode && chip->poll_count < 2) { - dev_dbg(chip->card->dev, - "azx_get_response timeout, polling the codec once: last cmd=0x%08x\n", - bus->last_cmd[addr]); - do_poll = 1; - chip->poll_count++; - goto again; - } - - - if (!chip->polling_mode) { + if (!bus->polling_mode) { dev_warn(chip->card->dev, "azx_get_response timeout, switching to polling mode: last cmd=0x%08x\n", bus->last_cmd[addr]); - chip->polling_mode = 1; + bus->polling_mode = 1; goto again; } @@ -987,20 +940,9 @@ return azx_rirb_get_response(bus, addr, res); } -static int azx_link_power(struct hdac_bus *bus, bool enable) -{ - struct azx *chip = bus_to_azx(bus); - - if (chip->ops->link_power) - return chip->ops->link_power(chip, enable); - else - return -EINVAL; -} - static const struct hdac_bus_ops bus_core_ops = { .command = azx_send_cmd, .get_response = azx_get_response, - .link_power = azx_link_power, }; #ifdef CONFIG_SND_HDA_DSP_LOADER @@ -1103,10 +1045,8 @@ void azx_stop_all_streams(struct azx *chip) { struct hdac_bus *bus = azx_bus(chip); - struct hdac_stream *s; - list_for_each_entry(s, &bus->stream_list, list) - snd_hdac_stream_stop(s); + snd_hdac_stop_streams(bus); } EXPORT_SYMBOL_GPL(azx_stop_all_streams); @@ -1228,36 +1168,13 @@ bus->in_reset = 0; } -static int get_jackpoll_interval(struct azx *chip) -{ - int i; - unsigned int j; - - if (!chip->jackpoll_ms) - return 0; - - i = chip->jackpoll_ms[chip->dev_index]; - if (i == 0) - return 0; - if (i < 50 || i > 60000) - j = 0; - else - j = msecs_to_jiffies(i); - if (j == 0) - dev_warn(chip->card->dev, - "jackpoll_ms value out of range: %d\n", i); - return j; -} - /* HD-audio bus initialization */ -int azx_bus_init(struct azx *chip, const char *model, - const struct hdac_io_ops *io_ops) +int azx_bus_init(struct azx *chip, const char *model) { struct hda_bus *bus = &chip->bus; int err; - err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops, - io_ops); + err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops); if (err < 0) return err; @@ -1277,15 +1194,8 @@ if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY) bus->core.align_bdle_4k = true; - /* AMD chipsets often cause the communication stalls upon certain - * sequence like the pin-detection. It seems that forcing the synced - * access works around the stall. Grrr... - */ - if (chip->driver_caps & AZX_DCAPS_SYNC_WRITE) { - dev_dbg(chip->card->dev, "Enable sync_write for stable communication\n"); - bus->core.sync_write = 1; - bus->allow_bus_reset = 1; - } + /* enable sync_write flag for stable communication as default */ + bus->core.sync_write = 1; return 0; } @@ -1331,7 +1241,7 @@ err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec); if (err < 0) continue; - codec->jackpoll_interval = get_jackpoll_interval(chip); + codec->jackpoll_interval = chip->jackpoll_interval; codec->beep_mode = chip->beep_mode; codecs++; } @@ -1348,17 +1258,24 @@ int azx_codec_configure(struct azx *chip) { struct hda_codec *codec, *next; + int success = 0; - /* use _safe version here since snd_hda_codec_configure() deregisters - * the device upon error and deletes itself from the bus list. - */ - list_for_each_codec_safe(codec, next, &chip->bus) { - snd_hda_codec_configure(codec); + list_for_each_codec(codec, &chip->bus) { + if (!snd_hda_codec_configure(codec)) + success++; } - if (!azx_bus(chip)->num_codecs) - return -ENODEV; - return 0; + if (success) { + /* unregister failed codecs if any codec has been probed */ + list_for_each_codec_safe(codec, next, &chip->bus) { + if (!codec->configured) { + codec_err(codec, "Unable to configure, disabling\n"); + snd_hdac_device_unregister(&codec->core); + } + } + } + + return success ? 0 : -ENODEV; } EXPORT_SYMBOL_GPL(azx_codec_configure); -- Gitblit v1.6.2