123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (c) 2013-2014, 2017-2018, The Linux Foundation. All rights reserved.
- */
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/device.h>
- #include <linux/mutex.h>
- #include <linux/miscdevice.h>
- #include <sound/audio_slimslave.h>
- #include <linux/slimbus/slimbus.h>
- #include <linux/pm_runtime.h>
- static struct slim_device *slim;
- static int vote_count;
- struct mutex suspend_lock;
- bool suspend;
- static int audio_slim_open(struct inode *inode, struct file *file)
- {
- pr_debug("%s:\n", __func__);
- if (vote_count) {
- pr_debug("%s: unvote: vote_count=%d\n", __func__, vote_count);
- pm_runtime_mark_last_busy(slim->dev.parent);
- pm_runtime_put(slim->dev.parent);
- vote_count--;
- }
- return 0;
- };
- static int audio_slim_release(struct inode *inode, struct file *file)
- {
- pr_debug("%s:\n", __func__);
- if (vote_count) {
- pr_debug("%s: unvote: vote_count=%d\n", __func__, vote_count);
- pm_runtime_mark_last_busy(slim->dev.parent);
- pm_runtime_put(slim->dev.parent);
- vote_count--;
- } else {
- pr_debug("%s: vote: vote_count=%d\n", __func__, vote_count);
- pm_runtime_get_sync(slim->dev.parent);
- vote_count++;
- }
- return 0;
- };
- static long audio_slim_ioctl(struct file *file, unsigned int cmd,
- unsigned long u_arg)
- {
- switch (cmd) {
- case AUDIO_SLIMSLAVE_VOTE:
- mutex_lock(&suspend_lock);
- if (!vote_count && !suspend) {
- pr_debug("%s:AUDIO_SLIMSLAVE_VOTE\n", __func__);
- pm_runtime_get_sync(slim->dev.parent);
- vote_count++;
- } else {
- pr_err("%s:Invalid vote: vote_count=%d suspend=%d\n",
- __func__, vote_count, suspend);
- }
- mutex_unlock(&suspend_lock);
- break;
- case AUDIO_SLIMSLAVE_UNVOTE:
- mutex_lock(&suspend_lock);
- if (vote_count && !suspend) {
- pr_debug("%s:AUDIO_SLIMSLAVE_UNVOTE\n", __func__);
- pm_runtime_mark_last_busy(slim->dev.parent);
- pm_runtime_put(slim->dev.parent);
- vote_count--;
- } else {
- pr_err("%s:Invalid unvote: vote_count=%d suspend=%d\n",
- __func__, vote_count, suspend);
- }
- mutex_unlock(&suspend_lock);
- break;
- default:
- pr_debug("%s: Invalid ioctl cmd: %d\n", __func__, cmd);
- break;
- }
- return 0;
- }
- static const struct file_operations audio_slimslave_fops = {
- .open = audio_slim_open,
- .unlocked_ioctl = audio_slim_ioctl,
- .release = audio_slim_release,
- };
- struct miscdevice audio_slimslave_misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = AUDIO_SLIMSLAVE_IOCTL_NAME,
- .fops = &audio_slimslave_fops,
- };
- static int audio_slimslave_probe(struct slim_device *audio_slim)
- {
- pr_debug("%s:\n", __func__);
- mutex_init(&suspend_lock);
- suspend = false;
- slim = audio_slim;
- misc_register(&audio_slimslave_misc);
- return 0;
- }
- static int audio_slimslave_remove(struct slim_device *audio_slim)
- {
- pr_debug("%s:\n", __func__);
- misc_deregister(&audio_slimslave_misc);
- return 0;
- }
- static int audio_slimslave_resume(struct slim_device *audio_slim)
- {
- pr_debug("%s:\n", __func__);
- mutex_lock(&suspend_lock);
- suspend = false;
- mutex_unlock(&suspend_lock);
- return 0;
- }
- static int audio_slimslave_suspend(struct slim_device *audio_slim,
- pm_message_t pmesg)
- {
- pr_debug("%s:\n", __func__);
- mutex_lock(&suspend_lock);
- suspend = true;
- mutex_unlock(&suspend_lock);
- return 0;
- }
- static const struct slim_device_id audio_slimslave_dt_match[] = {
- {"audio-slimslave", 0},
- {}
- };
- static struct slim_driver audio_slimslave_driver = {
- .driver = {
- .name = "audio-slimslave",
- .owner = THIS_MODULE,
- },
- .probe = audio_slimslave_probe,
- .remove = audio_slimslave_remove,
- .id_table = audio_slimslave_dt_match,
- .resume = audio_slimslave_resume,
- .suspend = audio_slimslave_suspend,
- };
- int __init audio_slimslave_init(void)
- {
- return slim_driver_register(&audio_slimslave_driver);
- }
- void audio_slimslave_exit(void)
- {
- slim_driver_unregister(&audio_slimslave_driver);
- }
- /* Module information */
- MODULE_DESCRIPTION("Audio side Slimbus slave driver");
- MODULE_LICENSE("GPL v2");
|