~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to sound/aoa/soundbus/i2sbus/control.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

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