Path: blob/master/sound/aoa/soundbus/i2sbus/control.c
15125 views
/*1* i2sbus driver -- bus control routines2*3* Copyright 2006 Johannes Berg <[email protected]>4*5* GPL v2, can be found in COPYING.6*/78#include <linux/kernel.h>9#include <linux/delay.h>10#include <linux/slab.h>1112#include <asm/io.h>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>1819#include "i2sbus.h"2021int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c)22{23*c = kzalloc(sizeof(struct i2sbus_control), GFP_KERNEL);24if (!*c)25return -ENOMEM;2627INIT_LIST_HEAD(&(*c)->list);2829(*c)->macio = dev->bus->chip;30return 0;31}3233void i2sbus_control_destroy(struct i2sbus_control *c)34{35kfree(c);36}3738/* this is serialised externally */39int i2sbus_control_add_dev(struct i2sbus_control *c,40struct i2sbus_dev *i2sdev)41{42struct device_node *np;4344np = i2sdev->sound.ofdev.dev.of_node;45i2sdev->enable = pmf_find_function(np, "enable");46i2sdev->cell_enable = pmf_find_function(np, "cell-enable");47i2sdev->clock_enable = pmf_find_function(np, "clock-enable");48i2sdev->cell_disable = pmf_find_function(np, "cell-disable");49i2sdev->clock_disable = pmf_find_function(np, "clock-disable");5051/* if the bus number is not 0 or 1 we absolutely need to use52* the platform functions -- there's nothing in Darwin that53* would allow seeing a system behind what the FCRs are then,54* and I don't want to go parsing a bunch of platform functions55* by hand to try finding a system... */56if (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)) {60pmf_put_function(i2sdev->enable);61pmf_put_function(i2sdev->cell_enable);62pmf_put_function(i2sdev->clock_enable);63pmf_put_function(i2sdev->cell_disable);64pmf_put_function(i2sdev->clock_disable);65return -ENODEV;66}6768list_add(&i2sdev->item, &c->list);6970return 0;71}7273void i2sbus_control_remove_dev(struct i2sbus_control *c,74struct i2sbus_dev *i2sdev)75{76/* this is serialised externally */77list_del(&i2sdev->item);78if (list_empty(&c->list))79i2sbus_control_destroy(c);80}8182int i2sbus_control_enable(struct i2sbus_control *c,83struct i2sbus_dev *i2sdev)84{85struct pmf_args args = { .count = 0 };86struct macio_chip *macio = c->macio;8788if (i2sdev->enable)89return pmf_call_one(i2sdev->enable, &args);9091if (macio == NULL || macio->base == NULL)92return -ENODEV;9394switch (i2sdev->bus_number) {95case 0:96/* these need to be locked or done through97* newly created feature calls! */98MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE);99break;100case 1:101MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_ENABLE);102break;103default:104return -ENODEV;105}106return 0;107}108109int i2sbus_control_cell(struct i2sbus_control *c,110struct i2sbus_dev *i2sdev,111int enable)112{113struct pmf_args args = { .count = 0 };114struct macio_chip *macio = c->macio;115116switch (enable) {117case 0:118if (i2sdev->cell_disable)119return pmf_call_one(i2sdev->cell_disable, &args);120break;121case 1:122if (i2sdev->cell_enable)123return pmf_call_one(i2sdev->cell_enable, &args);124break;125default:126printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n");127return -ENODEV;128}129130if (macio == NULL || macio->base == NULL)131return -ENODEV;132133switch (i2sdev->bus_number) {134case 0:135if (enable)136MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);137else138MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);139break;140case 1:141if (enable)142MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);143else144MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);145break;146default:147return -ENODEV;148}149return 0;150}151152int i2sbus_control_clock(struct i2sbus_control *c,153struct i2sbus_dev *i2sdev,154int enable)155{156struct pmf_args args = { .count = 0 };157struct macio_chip *macio = c->macio;158159switch (enable) {160case 0:161if (i2sdev->clock_disable)162return pmf_call_one(i2sdev->clock_disable, &args);163break;164case 1:165if (i2sdev->clock_enable)166return pmf_call_one(i2sdev->clock_enable, &args);167break;168default:169printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n");170return -ENODEV;171}172173if (macio == NULL || macio->base == NULL)174return -ENODEV;175176switch (i2sdev->bus_number) {177case 0:178if (enable)179MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);180else181MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);182break;183case 1:184if (enable)185MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);186else187MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);188break;189default:190return -ENODEV;191}192return 0;193}194195196