From 1543e317f1da31b75942316931e8f491a8920811 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 04 Jan 2024 10:08:02 +0000
Subject: [PATCH] disable FB
---
kernel/drivers/staging/most/sound/sound.c | 275 ++++++++++++++++++++++++++----------------------------
1 files changed, 134 insertions(+), 141 deletions(-)
diff --git a/kernel/drivers/staging/most/sound/sound.c b/kernel/drivers/staging/most/sound/sound.c
index fd9245d..b7666a7 100644
--- a/kernel/drivers/staging/most/sound/sound.c
+++ b/kernel/drivers/staging/most/sound/sound.c
@@ -10,18 +10,19 @@
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <linux/init.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <linux/sched.h>
#include <linux/kthread.h>
-#include <most/core.h>
+#include <linux/most.h>
#define DRIVER_NAME "sound"
+#define STRING_SIZE 80
-static struct list_head dev_list;
-static struct core_component comp;
+static struct most_component comp;
/**
* struct channel - private structure to keep channel specific data
@@ -49,12 +50,21 @@
unsigned int period_pos;
unsigned int buffer_pos;
bool is_stream_running;
-
struct task_struct *playback_task;
wait_queue_head_t playback_waitq;
-
void (*copy_fn)(void *alsa, void *most, unsigned int bytes);
};
+
+struct sound_adapter {
+ struct list_head dev_list;
+ struct most_interface *iface;
+ struct snd_card *card;
+ struct list_head list;
+ bool registered;
+ int pcm_dev_idx;
+};
+
+static struct list_head adpt_list;
#define MOST_PCM_INFO (SNDRV_PCM_INFO_MMAP | \
SNDRV_PCM_INFO_MMAP_VALID | \
@@ -159,13 +169,13 @@
static struct channel *get_channel(struct most_interface *iface,
int channel_id)
{
+ struct sound_adapter *adpt = iface->priv;
struct channel *channel, *tmp;
- list_for_each_entry_safe(channel, tmp, &dev_list, list) {
+ list_for_each_entry_safe(channel, tmp, &adpt->dev_list, list) {
if ((channel->iface == iface) && (channel->id == channel_id))
return channel;
}
-
return NULL;
}
@@ -209,7 +219,6 @@
channel->period_pos -= runtime->period_size;
return true;
}
-
return false;
}
@@ -249,7 +258,6 @@
if (period_elapsed)
snd_pcm_period_elapsed(channel->substream);
}
-
return 0;
}
@@ -267,6 +275,7 @@
struct channel *channel = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
struct most_channel_config *cfg = channel->cfg;
+ int ret;
channel->substream = substream;
@@ -279,11 +288,12 @@
}
}
- if (most_start_channel(channel->iface, channel->id, &comp)) {
+ ret = most_start_channel(channel->iface, channel->id, &comp);
+ if (ret) {
pr_err("most_start_channel() failed!\n");
if (cfg->direction == MOST_CH_TX)
kthread_stop(channel->playback_task);
- return -EBUSY;
+ return ret;
}
runtime->hw = channel->pcm_hardware;
@@ -307,48 +317,7 @@
if (channel->cfg->direction == MOST_CH_TX)
kthread_stop(channel->playback_task);
most_stop_channel(channel->iface, channel->id, &comp);
-
return 0;
-}
-
-/**
- * pcm_hw_params - implements hw_params callback function for PCM middle layer
- * @substream: sub-stream pointer
- * @hw_params: contains the hardware parameters set by the application
- *
- * This is called when the hardware parameters is set by the application, that
- * is, once when the buffer size, the period size, the format, etc. are defined
- * for the PCM substream. Many hardware setups should be done is this callback,
- * including the allocation of buffers.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct channel *channel = substream->private_data;
-
- if ((params_channels(hw_params) > channel->pcm_hardware.channels_max) ||
- (params_channels(hw_params) < channel->pcm_hardware.channels_min)) {
- pr_err("Requested number of channels not supported.\n");
- return -EINVAL;
- }
- return snd_pcm_lib_alloc_vmalloc_buffer(substream,
- params_buffer_bytes(hw_params));
-}
-
-/**
- * pcm_hw_free - implements hw_free callback function for PCM middle layer
- * @substream: substream pointer
- *
- * This is called to release the resources allocated via hw_params.
- * This function will be always called before the close callback is called.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_hw_free(struct snd_pcm_substream *substream)
-{
- return snd_pcm_lib_free_vmalloc_buffer(substream);
}
/**
@@ -389,14 +358,10 @@
channel->copy_fn = most_to_alsa_copy32;
}
- if (!channel->copy_fn) {
- pr_err("unsupported format\n");
+ if (!channel->copy_fn)
return -EINVAL;
- }
-
channel->period_pos = 0;
channel->buffer_pos = 0;
-
return 0;
}
@@ -425,7 +390,6 @@
return 0;
default:
- pr_info("%s(), invalid\n", __func__);
return -EINVAL;
}
return 0;
@@ -452,26 +416,16 @@
static const struct snd_pcm_ops pcm_ops = {
.open = pcm_open,
.close = pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = pcm_hw_params,
- .hw_free = pcm_hw_free,
.prepare = pcm_prepare,
.trigger = pcm_trigger,
.pointer = pcm_pointer,
- .page = snd_pcm_lib_get_vmalloc_page,
};
-static int split_arg_list(char *buf, char **card_name, u16 *ch_num,
- char **sample_res)
+static int split_arg_list(char *buf, u16 *ch_num, char **sample_res)
{
char *num;
int ret;
- *card_name = strsep(&buf, ".");
- if (!*card_name) {
- pr_err("Missing sound card name\n");
- return -EIO;
- }
num = strsep(&buf, "x");
if (!num)
goto err;
@@ -485,7 +439,7 @@
err:
pr_err("Bad PCM format\n");
- return -EIO;
+ return -EINVAL;
}
static const struct sample_resolution_info {
@@ -510,7 +464,7 @@
goto found;
}
pr_err("Unsupported PCM format\n");
- return -EIO;
+ return -EINVAL;
found:
if (!ch_num) {
@@ -538,6 +492,20 @@
return 0;
}
+static void release_adapter(struct sound_adapter *adpt)
+{
+ struct channel *channel, *tmp;
+
+ list_for_each_entry_safe(channel, tmp, &adpt->dev_list, list) {
+ list_del(&channel->list);
+ kfree(channel);
+ }
+ if (adpt->card)
+ snd_card_free(adpt->card);
+ list_del(&adpt->list);
+ kfree(adpt);
+}
+
/**
* audio_probe_channel - probe function of the driver module
* @iface: pointer to interface instance
@@ -552,31 +520,59 @@
*/
static int audio_probe_channel(struct most_interface *iface, int channel_id,
struct most_channel_config *cfg,
- char *arg_list)
+ char *device_name, char *arg_list)
{
struct channel *channel;
- struct snd_card *card;
+ struct sound_adapter *adpt;
struct snd_pcm *pcm;
int playback_count = 0;
int capture_count = 0;
int ret;
int direction;
- char *card_name;
u16 ch_num;
char *sample_res;
-
- if (!iface)
- return -EINVAL;
+ char arg_list_cpy[STRING_SIZE];
if (cfg->data_type != MOST_CH_SYNC) {
pr_err("Incompatible channel type\n");
return -EINVAL;
}
+ strlcpy(arg_list_cpy, arg_list, STRING_SIZE);
+ ret = split_arg_list(arg_list_cpy, &ch_num, &sample_res);
+ if (ret < 0)
+ return ret;
+ list_for_each_entry(adpt, &adpt_list, list) {
+ if (adpt->iface != iface)
+ continue;
+ if (adpt->registered)
+ return -ENOSPC;
+ adpt->pcm_dev_idx++;
+ goto skip_adpt_alloc;
+ }
+ adpt = kzalloc(sizeof(*adpt), GFP_KERNEL);
+ if (!adpt)
+ return -ENOMEM;
+
+ adpt->iface = iface;
+ INIT_LIST_HEAD(&adpt->dev_list);
+ iface->priv = adpt;
+ list_add_tail(&adpt->list, &adpt_list);
+ ret = snd_card_new(iface->driver_dev, -1, "INIC", THIS_MODULE,
+ sizeof(*channel), &adpt->card);
+ if (ret < 0)
+ goto err_free_adpt;
+ snprintf(adpt->card->driver, sizeof(adpt->card->driver),
+ "%s", DRIVER_NAME);
+ snprintf(adpt->card->shortname, sizeof(adpt->card->shortname),
+ "Microchip INIC");
+ snprintf(adpt->card->longname, sizeof(adpt->card->longname),
+ "%s at %s", adpt->card->shortname, iface->description);
+skip_adpt_alloc:
if (get_channel(iface, channel_id)) {
pr_err("channel (%s:%d) is already linked\n",
iface->description, channel_id);
- return -EINVAL;
+ return -EEXIST;
}
if (cfg->direction == MOST_CH_TX) {
@@ -586,54 +582,58 @@
capture_count = 1;
direction = SNDRV_PCM_STREAM_CAPTURE;
}
-
- ret = split_arg_list(arg_list, &card_name, &ch_num, &sample_res);
- if (ret < 0)
- return ret;
-
- ret = snd_card_new(&iface->dev, -1, card_name, THIS_MODULE,
- sizeof(*channel), &card);
- if (ret < 0)
- return ret;
-
- channel = card->private_data;
- channel->card = card;
+ channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+ if (!channel) {
+ ret = -ENOMEM;
+ goto err_free_adpt;
+ }
+ channel->card = adpt->card;
channel->cfg = cfg;
channel->iface = iface;
channel->id = channel_id;
init_waitqueue_head(&channel->playback_waitq);
+ list_add_tail(&channel->list, &adpt->dev_list);
ret = audio_set_hw_params(&channel->pcm_hardware, ch_num, sample_res,
cfg);
if (ret)
- goto err_free_card;
+ goto err_free_adpt;
- snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME);
- snprintf(card->shortname, sizeof(card->shortname), "Microchip MOST:%d",
- card->number);
- snprintf(card->longname, sizeof(card->longname), "%s at %s, ch %d",
- card->shortname, iface->description, channel_id);
+ ret = snd_pcm_new(adpt->card, device_name, adpt->pcm_dev_idx,
+ playback_count, capture_count, &pcm);
- ret = snd_pcm_new(card, card_name, 0, playback_count,
- capture_count, &pcm);
if (ret < 0)
- goto err_free_card;
+ goto err_free_adpt;
pcm->private_data = channel;
-
+ strscpy(pcm->name, device_name, sizeof(pcm->name));
snd_pcm_set_ops(pcm, direction, &pcm_ops);
-
- ret = snd_card_register(card);
- if (ret < 0)
- goto err_free_card;
-
- list_add_tail(&channel->list, &dev_list);
-
+ snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
return 0;
-err_free_card:
- snd_card_free(card);
+err_free_adpt:
+ release_adapter(adpt);
return ret;
+}
+
+static int audio_create_sound_card(void)
+{
+ int ret;
+ struct sound_adapter *adpt;
+
+ list_for_each_entry(adpt, &adpt_list, list) {
+ if (!adpt->registered)
+ goto adpt_alloc;
+ }
+ return -ENODEV;
+adpt_alloc:
+ ret = snd_card_register(adpt->card);
+ if (ret < 0) {
+ release_adapter(adpt);
+ return ret;
+ }
+ adpt->registered = true;
+ return 0;
}
/**
@@ -649,17 +649,17 @@
int channel_id)
{
struct channel *channel;
+ struct sound_adapter *adpt = iface->priv;
channel = get_channel(iface, channel_id);
- if (!channel) {
- pr_err("sound_disconnect_channel(), invalid channel %d\n",
- channel_id);
+ if (!channel)
return -EINVAL;
- }
list_del(&channel->list);
- snd_card_free(channel->card);
+ kfree(channel);
+ if (list_empty(&adpt->dev_list))
+ release_adapter(adpt);
return 0;
}
@@ -677,20 +677,13 @@
struct channel *channel = get_channel(mbo->ifp, mbo->hdm_channel_id);
bool period_elapsed = false;
- if (!channel) {
- pr_err("sound_rx_completion(), invalid channel %d\n",
- mbo->hdm_channel_id);
+ if (!channel)
return -EINVAL;
- }
-
if (channel->is_stream_running)
period_elapsed = copy_data(channel, mbo);
-
most_put_mbo(mbo);
-
if (period_elapsed)
snd_pcm_period_elapsed(channel->substream);
-
return 0;
}
@@ -709,48 +702,48 @@
{
struct channel *channel = get_channel(iface, channel_id);
- if (!channel) {
- pr_err("sound_tx_completion(), invalid channel %d\n",
- channel_id);
+ if (!channel)
return -EINVAL;
- }
wake_up_interruptible(&channel->playback_waitq);
-
return 0;
}
/**
- * Initialization of the struct core_component
+ * Initialization of the struct most_component
*/
-static struct core_component comp = {
+static struct most_component comp = {
+ .mod = THIS_MODULE,
.name = DRIVER_NAME,
.probe_channel = audio_probe_channel,
.disconnect_channel = audio_disconnect_channel,
.rx_completion = audio_rx_completion,
.tx_completion = audio_tx_completion,
+ .cfg_complete = audio_create_sound_card,
};
static int __init audio_init(void)
{
- pr_info("init()\n");
+ int ret;
- INIT_LIST_HEAD(&dev_list);
+ INIT_LIST_HEAD(&adpt_list);
- return most_register_component(&comp);
+ ret = most_register_component(&comp);
+ if (ret) {
+ pr_err("Failed to register %s\n", comp.name);
+ return ret;
+ }
+ ret = most_register_configfs_subsys(&comp);
+ if (ret) {
+ pr_err("Failed to register %s configfs subsys\n", comp.name);
+ most_deregister_component(&comp);
+ }
+ return ret;
}
static void __exit audio_exit(void)
{
- struct channel *channel, *tmp;
-
- pr_info("exit()\n");
-
- list_for_each_entry_safe(channel, tmp, &dev_list, list) {
- list_del(&channel->list);
- snd_card_free(channel->card);
- }
-
+ most_deregister_configfs_subsys(&comp);
most_deregister_component(&comp);
}
--
Gitblit v1.6.2