blob: b09506a05f18e26dc14c88027fedcbe53359e241 [file] [log] [blame]
Meng Wang688a8672019-01-29 13:43:33 +08001// SPDX-License-Identifier: GPL-2.0-only
Meng Wang61af6842018-09-10 17:47:55 +08002/*
3 * Copyright (c) 2013-2014, 2017-2018, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304 */
5
6#include <linux/init.h>
7#include <linux/module.h>
8#include <linux/fs.h>
9#include <linux/device.h>
10#include <linux/mutex.h>
11#include <linux/miscdevice.h>
12#include <sound/audio_slimslave.h>
13#include <linux/slimbus/slimbus.h>
14#include <linux/pm_runtime.h>
15
16static struct slim_device *slim;
17static int vote_count;
18struct mutex suspend_lock;
19bool suspend;
20
21static int audio_slim_open(struct inode *inode, struct file *file)
22{
23 pr_debug("%s:\n", __func__);
24
25 if (vote_count) {
26 pr_debug("%s: unvote: vote_count=%d\n", __func__, vote_count);
27 pm_runtime_mark_last_busy(slim->dev.parent);
28 pm_runtime_put(slim->dev.parent);
29 vote_count--;
30 }
31 return 0;
32};
33
34static int audio_slim_release(struct inode *inode, struct file *file)
35{
36 pr_debug("%s:\n", __func__);
37
38 if (vote_count) {
39 pr_debug("%s: unvote: vote_count=%d\n", __func__, vote_count);
40 pm_runtime_mark_last_busy(slim->dev.parent);
41 pm_runtime_put(slim->dev.parent);
42 vote_count--;
43 } else {
44 pr_debug("%s: vote: vote_count=%d\n", __func__, vote_count);
45 pm_runtime_get_sync(slim->dev.parent);
46 vote_count++;
47 }
48 return 0;
49};
50
51static long audio_slim_ioctl(struct file *file, unsigned int cmd,
52 unsigned long u_arg)
53{
54 switch (cmd) {
55 case AUDIO_SLIMSLAVE_VOTE:
56 mutex_lock(&suspend_lock);
57 if (!vote_count && !suspend) {
58 pr_debug("%s:AUDIO_SLIMSLAVE_VOTE\n", __func__);
59 pm_runtime_get_sync(slim->dev.parent);
60 vote_count++;
61 } else {
62 pr_err("%s:Invalid vote: vote_count=%d suspend=%d\n",
63 __func__, vote_count, suspend);
64 }
65 mutex_unlock(&suspend_lock);
66 break;
67 case AUDIO_SLIMSLAVE_UNVOTE:
68 mutex_lock(&suspend_lock);
69 if (vote_count && !suspend) {
70 pr_debug("%s:AUDIO_SLIMSLAVE_UNVOTE\n", __func__);
71 pm_runtime_mark_last_busy(slim->dev.parent);
72 pm_runtime_put(slim->dev.parent);
73 vote_count--;
74 } else {
75 pr_err("%s:Invalid unvote: vote_count=%d suspend=%d\n",
76 __func__, vote_count, suspend);
77 }
78 mutex_unlock(&suspend_lock);
79 break;
80 default:
81 pr_debug("%s: Invalid ioctl cmd: %d\n", __func__, cmd);
82 break;
83 }
84 return 0;
85}
86
87static const struct file_operations audio_slimslave_fops = {
88 .open = audio_slim_open,
89 .unlocked_ioctl = audio_slim_ioctl,
90 .release = audio_slim_release,
91};
92
93struct miscdevice audio_slimslave_misc = {
94 .minor = MISC_DYNAMIC_MINOR,
95 .name = AUDIO_SLIMSLAVE_IOCTL_NAME,
96 .fops = &audio_slimslave_fops,
97};
98
99static int audio_slimslave_probe(struct slim_device *audio_slim)
100{
101 pr_debug("%s:\n", __func__);
102
103 mutex_init(&suspend_lock);
104 suspend = false;
105 slim = audio_slim;
106 misc_register(&audio_slimslave_misc);
107 return 0;
108}
109
110static int audio_slimslave_remove(struct slim_device *audio_slim)
111{
112 pr_debug("%s:\n", __func__);
113
114 misc_deregister(&audio_slimslave_misc);
115 return 0;
116}
117
118static int audio_slimslave_resume(struct slim_device *audio_slim)
119{
120 pr_debug("%s:\n", __func__);
121
122 mutex_lock(&suspend_lock);
123 suspend = false;
124 mutex_unlock(&suspend_lock);
125 return 0;
126}
127
128static int audio_slimslave_suspend(struct slim_device *audio_slim,
129 pm_message_t pmesg)
130{
131 pr_debug("%s:\n", __func__);
132
133 mutex_lock(&suspend_lock);
134 suspend = true;
135 mutex_unlock(&suspend_lock);
136 return 0;
137}
138
139static const struct slim_device_id audio_slimslave_dt_match[] = {
140 {"audio-slimslave", 0},
141 {}
142};
143
144static struct slim_driver audio_slimslave_driver = {
145 .driver = {
146 .name = "audio-slimslave",
147 .owner = THIS_MODULE,
148 },
149 .probe = audio_slimslave_probe,
150 .remove = audio_slimslave_remove,
151 .id_table = audio_slimslave_dt_match,
152 .resume = audio_slimslave_resume,
153 .suspend = audio_slimslave_suspend,
154};
155
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530156int __init audio_slimslave_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530157{
158 return slim_driver_register(&audio_slimslave_driver);
159}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530160
Asish Bhattacharya5faacb32017-12-04 17:23:15 +0530161void audio_slimslave_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530162{
Laxminath Kasam30ad7512017-11-28 12:40:22 +0530163 slim_driver_unregister(&audio_slimslave_driver);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530164}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530165
166/* Module information */
167MODULE_DESCRIPTION("Audio side Slimbus slave driver");
168MODULE_LICENSE("GPL v2");