Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/aoa/soundbus/i2sbus/control.c
26481 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* i2sbus driver -- bus control routines
4
*
5
* Copyright 2006 Johannes Berg <[email protected]>
6
*/
7
8
#include <linux/kernel.h>
9
#include <linux/delay.h>
10
#include <linux/slab.h>
11
#include <linux/io.h>
12
13
#include <asm/macio.h>
14
#include <asm/pmac_feature.h>
15
#include <asm/pmac_pfunc.h>
16
#include <asm/keylargo.h>
17
18
#include "i2sbus.h"
19
20
int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c)
21
{
22
*c = kzalloc(sizeof(struct i2sbus_control), GFP_KERNEL);
23
if (!*c)
24
return -ENOMEM;
25
26
INIT_LIST_HEAD(&(*c)->list);
27
28
(*c)->macio = dev->bus->chip;
29
return 0;
30
}
31
32
void i2sbus_control_destroy(struct i2sbus_control *c)
33
{
34
kfree(c);
35
}
36
37
/* this is serialised externally */
38
int i2sbus_control_add_dev(struct i2sbus_control *c,
39
struct i2sbus_dev *i2sdev)
40
{
41
struct device_node *np;
42
43
np = i2sdev->sound.ofdev.dev.of_node;
44
i2sdev->enable = pmf_find_function(np, "enable");
45
i2sdev->cell_enable = pmf_find_function(np, "cell-enable");
46
i2sdev->clock_enable = pmf_find_function(np, "clock-enable");
47
i2sdev->cell_disable = pmf_find_function(np, "cell-disable");
48
i2sdev->clock_disable = pmf_find_function(np, "clock-disable");
49
50
/* if the bus number is not 0 or 1 we absolutely need to use
51
* the platform functions -- there's nothing in Darwin that
52
* would allow seeing a system behind what the FCRs are then,
53
* and I don't want to go parsing a bunch of platform functions
54
* by hand to try finding a system... */
55
if (i2sdev->bus_number != 0 && i2sdev->bus_number != 1 &&
56
(!i2sdev->enable ||
57
!i2sdev->cell_enable || !i2sdev->clock_enable ||
58
!i2sdev->cell_disable || !i2sdev->clock_disable)) {
59
pmf_put_function(i2sdev->enable);
60
pmf_put_function(i2sdev->cell_enable);
61
pmf_put_function(i2sdev->clock_enable);
62
pmf_put_function(i2sdev->cell_disable);
63
pmf_put_function(i2sdev->clock_disable);
64
return -ENODEV;
65
}
66
67
list_add(&i2sdev->item, &c->list);
68
69
return 0;
70
}
71
72
void i2sbus_control_remove_dev(struct i2sbus_control *c,
73
struct i2sbus_dev *i2sdev)
74
{
75
/* this is serialised externally */
76
list_del(&i2sdev->item);
77
if (list_empty(&c->list))
78
i2sbus_control_destroy(c);
79
}
80
81
int i2sbus_control_enable(struct i2sbus_control *c,
82
struct i2sbus_dev *i2sdev)
83
{
84
struct pmf_args args = { .count = 0 };
85
struct macio_chip *macio = c->macio;
86
87
if (i2sdev->enable)
88
return pmf_call_one(i2sdev->enable, &args);
89
90
if (macio == NULL || macio->base == NULL)
91
return -ENODEV;
92
93
switch (i2sdev->bus_number) {
94
case 0:
95
/* these need to be locked or done through
96
* newly created feature calls! */
97
MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE);
98
break;
99
case 1:
100
MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_ENABLE);
101
break;
102
default:
103
return -ENODEV;
104
}
105
return 0;
106
}
107
108
int i2sbus_control_cell(struct i2sbus_control *c,
109
struct i2sbus_dev *i2sdev,
110
int enable)
111
{
112
struct pmf_args args = { .count = 0 };
113
struct macio_chip *macio = c->macio;
114
115
switch (enable) {
116
case 0:
117
if (i2sdev->cell_disable)
118
return pmf_call_one(i2sdev->cell_disable, &args);
119
break;
120
case 1:
121
if (i2sdev->cell_enable)
122
return pmf_call_one(i2sdev->cell_enable, &args);
123
break;
124
default:
125
printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n");
126
return -ENODEV;
127
}
128
129
if (macio == NULL || macio->base == NULL)
130
return -ENODEV;
131
132
switch (i2sdev->bus_number) {
133
case 0:
134
if (enable)
135
MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);
136
else
137
MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);
138
break;
139
case 1:
140
if (enable)
141
MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);
142
else
143
MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);
144
break;
145
default:
146
return -ENODEV;
147
}
148
return 0;
149
}
150
151
int i2sbus_control_clock(struct i2sbus_control *c,
152
struct i2sbus_dev *i2sdev,
153
int enable)
154
{
155
struct pmf_args args = { .count = 0 };
156
struct macio_chip *macio = c->macio;
157
158
switch (enable) {
159
case 0:
160
if (i2sdev->clock_disable)
161
return pmf_call_one(i2sdev->clock_disable, &args);
162
break;
163
case 1:
164
if (i2sdev->clock_enable)
165
return pmf_call_one(i2sdev->clock_enable, &args);
166
break;
167
default:
168
printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n");
169
return -ENODEV;
170
}
171
172
if (macio == NULL || macio->base == NULL)
173
return -ENODEV;
174
175
switch (i2sdev->bus_number) {
176
case 0:
177
if (enable)
178
MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);
179
else
180
MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);
181
break;
182
case 1:
183
if (enable)
184
MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);
185
else
186
MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);
187
break;
188
default:
189
return -ENODEV;
190
}
191
return 0;
192
}
193
194