linux/sound/aoa/soundbus/i2sbus/control.c
<<
>>
Prefs
   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#include <linux/io.h>
  13
  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
  22int 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
  34void i2sbus_control_destroy(struct i2sbus_control *c)
  35{
  36        kfree(c);
  37}
  38
  39/* this is serialised externally */
  40int 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
  74void 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
  83int 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
 110int 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
 153int 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}
 195