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