// SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2014, 2016-2017 The Linux Foundation. All rights reserved. */ #include #include #include #include #include #include #include "msm-pcm-routing-devdep.h" #include "msm-ds2-dap-config.h" #ifdef CONFIG_SND_HWDEP static int msm_pcm_routing_hwdep_open(struct snd_hwdep *hw, struct file *file) { pr_debug("%s\n", __func__); msm_ds2_dap_update_port_parameters(hw, file, true); return 0; } static int msm_pcm_routing_hwdep_release(struct snd_hwdep *hw, struct file *file) { pr_debug("%s\n", __func__); msm_ds2_dap_update_port_parameters(hw, file, false); return 0; } static int msm_pcm_routing_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; void __user *argp = (void __user *)arg; pr_debug("%s:cmd %x\n", __func__, cmd); switch (cmd) { case SNDRV_DEVDEP_DAP_IOCTL_SET_PARAM: case SNDRV_DEVDEP_DAP_IOCTL_GET_PARAM: case SNDRV_DEVDEP_DAP_IOCTL_DAP_COMMAND: case SNDRV_DEVDEP_DAP_IOCTL_DAP_LICENSE: msm_pcm_routing_acquire_lock(); ret = msm_ds2_dap_ioctl(hw, file, cmd, argp); msm_pcm_routing_release_lock(); break; case SNDRV_DEVDEP_DAP_IOCTL_GET_VISUALIZER: ret = msm_ds2_dap_ioctl(hw, file, cmd, argp); break; default: pr_err("%s called with invalid control 0x%X\n", __func__, cmd); ret = -EINVAL; break; } return ret; } void msm_pcm_routing_hwdep_free(struct snd_pcm *pcm) { pr_debug("%s\n", __func__); } #ifdef CONFIG_COMPAT static int msm_pcm_routing_hwdep_compat_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; void __user *argp = (void __user *)arg; pr_debug("%s:cmd %x\n", __func__, cmd); switch (cmd) { case SNDRV_DEVDEP_DAP_IOCTL_SET_PARAM32: case SNDRV_DEVDEP_DAP_IOCTL_GET_PARAM32: case SNDRV_DEVDEP_DAP_IOCTL_DAP_COMMAND32: case SNDRV_DEVDEP_DAP_IOCTL_DAP_LICENSE32: msm_pcm_routing_acquire_lock(); ret = msm_ds2_dap_compat_ioctl(hw, file, cmd, argp); msm_pcm_routing_release_lock(); break; case SNDRV_DEVDEP_DAP_IOCTL_GET_VISUALIZER32: ret = msm_ds2_dap_compat_ioctl(hw, file, cmd, argp); break; default: pr_err("%s called with invalid control 0x%X\n", __func__, cmd); ret = -EINVAL; break; } return ret; } #endif int msm_pcm_routing_hwdep_new(struct snd_soc_pcm_runtime *runtime, struct msm_pcm_routing_bdai_data *msm_bedais) { struct snd_hwdep *hwdep; struct snd_soc_dai_link *dai_link = runtime->dai_link; int rc; if (dai_link->id < 0 || dai_link->id >= MSM_BACKEND_DAI_MAX) { pr_err("%s:BE id %d invalid index\n", __func__, dai_link->id); return -EINVAL; } pr_debug("%s BE id %d\n", __func__, dai_link->id); rc = snd_hwdep_new(runtime->card->snd_card, msm_bedais[dai_link->id].name, dai_link->id, &hwdep); if (hwdep == NULL) { pr_err("%s: hwdep intf failed to create %s- hwdep NULL\n", __func__, msm_bedais[dai_link->id].name); return rc; } if (rc < 0) { pr_err("%s: hwdep intf failed to create %s rc %d\n", __func__, msm_bedais[dai_link->id].name, rc); return rc; } hwdep->iface = SNDRV_HWDEP_IFACE_AUDIO_BE; hwdep->private_data = &msm_bedais[dai_link->id]; hwdep->ops.open = msm_pcm_routing_hwdep_open; hwdep->ops.ioctl = msm_pcm_routing_hwdep_ioctl; hwdep->ops.release = msm_pcm_routing_hwdep_release; #ifdef CONFIG_COMPAT hwdep->ops.ioctl_compat = msm_pcm_routing_hwdep_compat_ioctl; #endif return rc; } #endif