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