summaryrefslogtreecommitdiff
path: root/drivers/misc/i2s/i2s.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/i2s/i2s.c')
-rwxr-xr-xdrivers/misc/i2s/i2s.c632
1 files changed, 0 insertions, 632 deletions
diff --git a/drivers/misc/i2s/i2s.c b/drivers/misc/i2s/i2s.c
deleted file mode 100755
index 9d14088cebc..00000000000
--- a/drivers/misc/i2s/i2s.c
+++ /dev/null
@@ -1,632 +0,0 @@
-/*----------------------------------------------------------------------------*/
-/* copyright STMicroelectronics, 2007. */
-/* */
-/* This program is free software; you can redistribute it and/or modify it */
-/* under the terms of the GNU General Public License as published by the Free */
-/* Software Foundation; either version 2.1 of the License, or (at your option)*/
-/* any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, but */
-/* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY */
-/* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License */
-/* for more details. */
-/* */
-/* You should have received a copy of the GNU General Public License */
-/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
-/*----------------------------------------------------------------------------*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/cache.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/idr.h>
-#include <linux/i2s/i2s.h>
-#include <linux/platform_device.h>
-
-/*******************************************************************************/
-static DEFINE_MUTEX(core_lock);
-
-static void i2sdev_release(struct device *dev)
-{
- struct i2s_device *i2s = to_i2s_device(dev);
-
- if (i2s->controller)
- put_device(&(i2s->controller->dev));
- kfree(dev);
-}
-static ssize_t
-modalias_show(struct device *dev, struct device_attribute *a, char *buf)
-{
- const struct i2s_device *i2s = to_i2s_device(dev);
- return sprintf(buf, "%s\n", i2s->modalias);
-}
-
-static struct device_attribute i2s_dev_attrs[] = {
- __ATTR_RO(modalias),
- __ATTR_NULL,
-};
-
-/* modalias support makes "modprobe $MODALIAS" new-style hotplug work,
- * and the sysfs version makes coldplug work too.
- */
-static const struct i2s_device_id *i2s_match_id(const struct i2s_device_id *id,
- const struct i2s_device *device)
-{
- while (id->name[0]) {
- if (strcmp(device->modalias, id->name) == 0)
- return id;
- id++;
- }
- return NULL;
-}
-
-static int i2s_match_device(struct device *dev, struct device_driver *drv)
-{
- const struct i2s_device *device = to_i2s_device(dev);
- struct i2s_driver *driver = to_i2s_driver(drv);
- if (driver->id_table)
- return i2s_match_id(driver->id_table, device) != NULL;
- return 0;
-}
-
-static int i2s_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- const struct i2s_device *i2s = to_i2s_device(dev);
-
- add_uevent_var(env, "MODALIAS=%s", i2s->modalias);
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int i2s_suspend(struct device *dev, pm_message_t message)
-{
- int value = 0;
- struct i2s_driver *drv = to_i2s_driver(dev->driver);
-
- /* suspend will stop irqs and dma; no more i/o */
- if (drv) {
- if (drv->suspend)
- value = drv->suspend(to_i2s_device(dev), message);
- else
- dev_dbg(dev, "... can't suspend\n");
- }
- return value;
-}
-
-static int i2s_resume(struct device *dev)
-{
- int value = 0;
- struct i2s_driver *drv = to_i2s_driver(dev->driver);
-
- /* resume may restart the i/o queue */
- if (drv) {
- if (drv->resume)
- value = drv->resume(to_i2s_device(dev));
- else
- dev_dbg(dev, "... can't resume\n");
- }
- return value;
-}
-
-#else
-#define i2s_suspend NULL
-#define i2s_resume NULL
-#endif
-
-/*This bus is designed to handle various protocols supported by the MSP- ARM Primecell IP
- * such as
- * I2s, PCM, AC97, TDM .... (refer to the data sheet for the complete list.
- * Current MSP driver has the above ones coded.
- * */
-struct bus_type i2s_bus_type = {
- .name = "i2s",
- .dev_attrs = i2s_dev_attrs,
- .match = i2s_match_device,
- .uevent = i2s_uevent,
- .suspend = i2s_suspend,
- .resume = i2s_resume,
-};
-
-EXPORT_SYMBOL_GPL(i2s_bus_type);
-
-static int i2s_drv_probe(struct device *dev)
-{
- const struct i2s_driver *sdrv = to_i2s_driver(dev->driver);
-
- return sdrv->probe(to_i2s_device(dev));
-}
-
-static int i2s_drv_remove(struct device *dev)
-{
- const struct i2s_driver *sdrv = to_i2s_driver(dev->driver);
-
- return sdrv->remove(to_i2s_device(dev));
-}
-
-static void i2s_drv_shutdown(struct device *dev)
-{
- const struct i2s_driver *sdrv = to_i2s_driver(dev->driver);
-
- sdrv->shutdown(to_i2s_device(dev));
-}
-
-/**
- * i2s_register_driver - register a I2S driver
- * @sdrv: the driver to register
- * Context: can sleep
- */
-int i2s_register_driver(struct i2s_driver *sdrv)
-{
- sdrv->driver.bus = &i2s_bus_type;
- if (sdrv->probe)
- sdrv->driver.probe = i2s_drv_probe;
- if (sdrv->remove)
- sdrv->driver.remove = i2s_drv_remove;
- if (sdrv->shutdown)
- sdrv->driver.shutdown = i2s_drv_shutdown;
- return driver_register(&sdrv->driver);
-}
-
-EXPORT_SYMBOL_GPL(i2s_register_driver);
-
-/******************************************************************************/
-struct board_i2s_combined_info {
- struct i2s_board_info board_info;
- struct i2s_device *i2s_dev_p;
-};
-struct boardinfo {
- struct list_head list;
- unsigned n_board_info;
- struct board_i2s_combined_info board_i2s_info[0];
-};
-
-static LIST_HEAD(board_list);
-static DEFINE_MUTEX(board_lock);
-
-/*
- * Get an i2s device. Used in MSP LTP tests.
- */
-struct i2s_device *i2s_get_device_from_boardinfo(int chip_select)
-{
- struct boardinfo *bi;
- struct i2s_device *i2s_dev_p = NULL;
-
- mutex_lock(&board_lock);
- list_for_each_entry(bi, &board_list, list) {
- struct board_i2s_combined_info *chip = bi->board_i2s_info;
- unsigned n;
-
- for (n = bi->n_board_info; n > 0; n--, chip++)
- if (chip->board_info.chip_select == chip_select) {
- i2s_dev_p = chip->i2s_dev_p;
- break;
- }
- if (i2s_dev_p != NULL)
- break;
- }
- mutex_unlock(&board_lock);
-
- return i2s_dev_p;
-}
-
-EXPORT_SYMBOL_GPL(i2s_get_device_from_boardinfo);
-
-/* I2S devices should normally not be created by I2S device drivers; that
- * would make them board-specific. Similarly with I2S master drivers.
- * Device registration normally goes into like arch/.../mach.../board-YYY.c
- * with other readonly (flashable) information about mainboard devices.
- */
-struct i2s_device *i2s_alloc_device(struct device *device)
-{
- struct i2s_device *i2s;
- struct device *dev = device->parent;
-
- get_device(device);
- i2s = kzalloc(sizeof *i2s, GFP_KERNEL);
- if (!i2s) {
- dev_err(dev, "cannot alloc i2s_device\n");
- return NULL;
- }
-
- i2s->dev.parent = dev;
- i2s->dev.bus = &i2s_bus_type;
- i2s->dev.release = i2sdev_release;
- device_initialize(&i2s->dev);
- return i2s;
-}
-
-EXPORT_SYMBOL_GPL(i2s_alloc_device);
-
-/**
- * i2s_add_device - Add i2s_device allocated with i2s_alloc_device
- * @i2s: i2s_device to register
- *
- * Companion function to i2s_alloc_device. Devices allocated with
- * i2s_alloc_device can be added onto the i2s bus with this function.
- *
- * Returns 0 on success; negative errno on failure
- */
-int i2s_add_device(struct i2s_device *i2s)
-{
- static DEFINE_MUTEX(i2s_add_lock);
- struct device *dev = i2s->dev.parent;
- int status;
-
- dev_set_name(&i2s->dev, "%s.%u", "i2s", i2s->chip_select);
-
- mutex_lock(&i2s_add_lock);
-
- if (bus_find_device_by_name(&i2s_bus_type, NULL, dev_name(&i2s->dev))
- != NULL) {
- dev_err(dev, "chipselect %d already in use\n",
- i2s->chip_select);
- status = -EBUSY;
- goto done;
- }
-
- /* Device may be bound to an active driver when this returns */
- status = device_add(&i2s->dev);
- if (status < 0)
- dev_err(dev, "can't %s %s, status %d\n",
- "add", dev_name(&i2s->dev), status);
- else
- dev_dbg(dev, "registered child %s\n", dev_name(&i2s->dev));
-
- done:
- mutex_unlock(&i2s_add_lock);
- return status;
-}
-
-EXPORT_SYMBOL_GPL(i2s_add_device);
-
-/**
- * i2s_new_device - instantiate one new I2S device
- * @i2s_cont: Controller to which device is connected
- * @chip: Describes the I2S device
- * Context: can sleep
- *
- * On typical mainboards, this is purely internal; and it's not needed
- * after board init creates the hard-wired devices. Some development
- * platforms may not be able to use i2s_register_board_info though, and
- * this is exported so that driver could add devices (which it would
- * learn about out-of-band).
- *
- * Returns the new device, or NULL.
- */
-struct i2s_device *i2s_new_device(struct i2s_controller *i2s_cont,
- struct i2s_board_info *chip)
-{
- struct i2s_device *proxy;
- int status;
-
- /* NOTE: caller did any chip->bus_num checks necessary.
- *
- * Also, unless we change the return value convention to use
- * error-or-pointer (not NULL-or-pointer), troubleshootability
- * suggests syslogged diagnostics are best here (ugh).
- */
-
- proxy = i2s_alloc_device(&i2s_cont->dev);
- if (!proxy)
- return NULL;
-
- WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
-
- proxy->chip_select = chip->chip_select;
- strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
- proxy->dev.platform_data = (void *)chip->platform_data;
- proxy->controller = i2s_cont;
-
- status = i2s_add_device(proxy);
- if (status < 0) {
- kfree(proxy);
- return NULL;
- }
-
- return proxy;
-}
-
-EXPORT_SYMBOL_GPL(i2s_new_device);
-
-/**
- * i2s_register_board_info - register I2S devices for a given board
- * @info: array of chip descriptors
- * @n: how many descriptors are provided
- * Context: can sleep
- *
- * Board-specific early init code calls this (probably during arch_initcall)
- * with segments of the I2S device table. Any device nodes are created later,
- * after the relevant parent I2S controller (id) is defined. We keep
- * this table of devices forever, so that reloading a controller driver will
- * not make Linux forget about these hard-wired devices.
- *
- */
-int __init
-i2s_register_board_info(struct i2s_board_info const *info, unsigned n)
-{
- int i;
- struct boardinfo *bi;
-
- bi = kmalloc(sizeof(*bi) + (n * sizeof(struct board_i2s_combined_info)), GFP_KERNEL);
- if (!bi)
- return -ENOMEM;
- bi->n_board_info = n;
-
- for (i = 0; i < n; i++)
- memcpy(&bi->board_i2s_info[i].board_info, &info[i], sizeof *info);
-
- mutex_lock(&board_lock);
- list_add_tail(&bi->list, &board_list);
- mutex_unlock(&board_lock);
- return 0;
-}
-
-/**
- * scan_boardinfo - Scan, creates and registered new i2s device structure.
- * @i2s_cont: i2s controller structure
- * Context: process
- *
- * It will scan the device list that may be registered statically using
- * register_board_info func in arch specific directory and call
- * i2s_new_device to create and registered i2s device over i2s bus. It is
- * called by i2s_add_controller function.
- *
- * Returns void.
- */
-static void scan_boardinfo(struct i2s_controller *i2s_cont)
-{
- struct boardinfo *bi;
-
- mutex_lock(&board_lock);
- list_for_each_entry(bi, &board_list, list) {
- struct board_i2s_combined_info *chip = bi->board_i2s_info;
- unsigned n;
-
- for (n = bi->n_board_info; n > 0; n--, chip++) {
- if (chip->board_info.chip_select != i2s_cont->id)
- continue;
- /* NOTE: this relies on i2s_new_device to
- * issue diagnostics when given bogus inputs
- */
- chip->i2s_dev_p = i2s_new_device(i2s_cont, &chip->board_info);
- }
- }
- mutex_unlock(&board_lock);
-}
-
-/******************************************************************************/
-/**I2S Controller inittialization*/
-static void i2s_controller_dev_release(struct device *dev)
-{
- struct i2s_controller *i2s_cont;
- i2s_cont = container_of(dev, struct i2s_controller, dev);
- kfree(i2s_cont);
-}
-
-static ssize_t
-show_controller_name(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct i2s_controller *cont = to_i2s_controller(dev);
- return sprintf(buf, "%s\n", cont->name);
-}
-
-static struct device_attribute i2s_controller_attrs[] = {
- __ATTR(name, S_IRUGO, show_controller_name, NULL),
- {},
-};
-
-static struct class i2s_controller_class = {
- .owner = THIS_MODULE,
- .name = "i2s-controller",
- .dev_attrs = i2s_controller_attrs,
-};
-
-static int i2s_register_controller(struct i2s_controller *cont)
-{
- int res = 0;
- mutex_init(&cont->bus_lock);
-
- mutex_lock(&core_lock);
-
- /* Add the controller to the driver core.
- * If the parent pointer is not set up,
- * we add this controller to the host bus.
- */
- if (cont->dev.parent == NULL) {
- cont->dev.parent = &platform_bus;
- pr_debug("I2S controller driver [%s] forgot to specify "
- "physical device\n", cont->name);
- }
- dev_set_name(&cont->dev, "I2Scrlr-%d", cont->id);
- cont->dev.release = &i2s_controller_dev_release;
- cont->dev.class = &i2s_controller_class;
- res = device_register(&cont->dev);
- if (res)
- goto out_unlock;
-
- dev_dbg(&cont->dev, "controller [%s] registered\n", cont->name);
- scan_boardinfo(cont);
- out_unlock:
- mutex_unlock(&core_lock);
- return res;
-}
-
-/**
- * i2s_add_controller - declare i2s controller, use dynamic bus number
- * @controller: the controller to add
- * Context: can sleep
- *
- */
-int i2s_add_controller(struct i2s_controller *controller)
-{
- return i2s_register_controller(controller);
-}
-
-EXPORT_SYMBOL(i2s_add_controller);
-
-static int __unregister(struct device *dev, void *controller_dev)
-{
- /* note: before about 2.6.14-rc1 this would corrupt memory: */
- if (dev != controller_dev)
- i2s_unregister_device(to_i2s_device(dev));
- return 0;
-}
-
-/**
- * i2s_del_controller - unregister I2S controller
- * @cont: the controller being unregistered
- * Context: can sleep
- *
- * This unregisters an I2S controller which was previously registered
- * by @i2s_add_controller.
- */
-int i2s_del_controller(struct i2s_controller *cont)
-{
- int res = 0;
- int dummy;
- mutex_lock(&core_lock);
-
- dummy = device_for_each_child(cont->dev.parent, &cont->dev,
- __unregister);
- device_unregister(&cont->dev);
- mutex_unlock(&core_lock);
- return res;
-}
-
-EXPORT_SYMBOL(i2s_del_controller);
-
-/******************************************************************************/
-/*I2S interface apis*/
-
-/**
- * i2s_transfer - Main i2s transfer function.
- * @i2s_cont: i2s controller structure passed by client driver.
- * @message: i2s message structure contains transceive info.
- * Context: process or interrupt.
- *
- * This API is called by client i2s driver as i2s_xfer funtion. It will handle
- * main i2s transfer over i2s bus. The controller should registered its own
- * functions using i2s algorithm structure.
- *
- * Returns error(-1) in case of failure or success(0).
- */
-int i2s_transfer(struct i2s_controller *i2s_cont, struct i2s_message *message)
-{
- return i2s_cont->algo->cont_transfer(i2s_cont, message);
-
-}
-
-EXPORT_SYMBOL(i2s_transfer);
-
-/**
- * i2s_cleanup - Close the current i2s connection btw controller and client.
- * @i2s_cont: i2s controller structure
- * @flag: It indicates the functionality that needs to be disabled.
- * Context: process
- *
- * This API will disable and reset the controller's configuration. Reset the
- * controller so that i2s client driver can reconfigure with new configuration.
- * Controller should release all the necessary resources which was acquired
- * during setup.
- *
- * Returns error(-1) in case of failure or success(0).
- */
-int i2s_cleanup(struct i2s_controller *i2s_cont, i2s_flag flag)
-{
- int status = 0;
- status = i2s_cont->algo->cont_cleanup(i2s_cont, flag);
- if (status)
- return -1;
- else
- return 0;
-}
-
-EXPORT_SYMBOL(i2s_cleanup);
-
-/**
- * i2s_setup - configures and enables the I2S controller.
- * @i2s_cont: i2s controller sent by i2s device.
- * @config: specifies the configuration parameters.
- *
- * This function configures the I2S controller with the client configuration.
- * Controller was already registered on I2S bus by some master controller
- * driver.
- *
- * Returns error(-1) in case of failure else success(0)
- */
-int i2s_setup(struct i2s_controller *i2s_cont, void *config)
-{
- return i2s_cont->algo->cont_setup(i2s_cont, config);
-}
-
-EXPORT_SYMBOL(i2s_setup);
-
-/**
- * i2s_hw_status - Get the current hw status for the i2s controller.
- * @i2s_cont: i2s controller structure passed by client driver.
- * Context: process or interrupt.
- *
- * This API is called by client i2s driver to find out current hw status.
- * The controller should registered its own functions using i2s algorithm structure.
- *
- * Returns current hw status register.
- */
-int i2s_hw_status(struct i2s_controller *i2s_cont)
-{
- return i2s_cont->algo->cont_hw_status(i2s_cont);
-}
-
-/**
- * i2s_get_pointer - Get the current dma_addr_t for the i2s controller.
- * @i2s_cont: i2s controller structure passed by client driver.
- * @i2s_direction: Specifies TX or RX direction.
- * Context: process or interrupt.
- *
- * This API is called by client i2s driver to return a dma_addr_t corresponding
- * to the position of the DMA-controller.
- * The controller should registered its own functions using i2s algorithm structure.
- *
- * Returns current hw status register.
- */
-dma_addr_t i2s_get_pointer(struct i2s_controller *i2s_cont,
- enum i2s_direction_t i2s_direction)
-{
- return i2s_cont->algo->cont_get_pointer(i2s_cont, i2s_direction);
-}
-
-/******************************************************************************/
-
-static int __init i2s_init(void)
-{
- int status;
-
- status = bus_register(&i2s_bus_type);
- if (status < 0)
- goto err0;
-
- status = class_register(&i2s_controller_class);
- if (status < 0)
- goto err1;
- return 0;
-
- err1:
- bus_unregister(&i2s_bus_type);
- err0:
- return status;
-}
-
-static void __exit i2s_exit(void)
-{
- class_unregister(&i2s_controller_class);
- bus_unregister(&i2s_bus_type);
-}
-
-subsys_initcall(i2s_init);
-module_exit(i2s_exit);
-
-MODULE_AUTHOR("Sandeep Kaushik, <sandeep-mmc.kaushik@st.com>");
-MODULE_LICENSE("GPL");