linux/drivers/mfd/davinci_voicecodec.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * DaVinci Voice Codec Core Interface for TI platforms
   4 *
   5 * Copyright (C) 2010 Texas Instruments, Inc
   6 *
   7 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
   8 */
   9
  10#include <linux/init.h>
  11#include <linux/module.h>
  12#include <linux/device.h>
  13#include <linux/slab.h>
  14#include <linux/delay.h>
  15#include <linux/io.h>
  16#include <linux/clk.h>
  17#include <linux/regmap.h>
  18
  19#include <sound/pcm.h>
  20
  21#include <linux/mfd/davinci_voicecodec.h>
  22
  23static const struct regmap_config davinci_vc_regmap = {
  24        .reg_bits = 32,
  25        .val_bits = 32,
  26};
  27
  28static int __init davinci_vc_probe(struct platform_device *pdev)
  29{
  30        struct davinci_vc *davinci_vc;
  31        struct resource *res;
  32        struct mfd_cell *cell = NULL;
  33        dma_addr_t fifo_base;
  34        int ret;
  35
  36        davinci_vc = devm_kzalloc(&pdev->dev,
  37                                  sizeof(struct davinci_vc), GFP_KERNEL);
  38        if (!davinci_vc)
  39                return -ENOMEM;
  40
  41        davinci_vc->clk = devm_clk_get(&pdev->dev, NULL);
  42        if (IS_ERR(davinci_vc->clk)) {
  43                dev_dbg(&pdev->dev,
  44                            "could not get the clock for voice codec\n");
  45                return -ENODEV;
  46        }
  47        clk_enable(davinci_vc->clk);
  48
  49        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  50
  51        fifo_base = (dma_addr_t)res->start;
  52        davinci_vc->base = devm_ioremap_resource(&pdev->dev, res);
  53        if (IS_ERR(davinci_vc->base)) {
  54                ret = PTR_ERR(davinci_vc->base);
  55                goto fail;
  56        }
  57
  58        davinci_vc->regmap = devm_regmap_init_mmio(&pdev->dev,
  59                                                   davinci_vc->base,
  60                                                   &davinci_vc_regmap);
  61        if (IS_ERR(davinci_vc->regmap)) {
  62                ret = PTR_ERR(davinci_vc->regmap);
  63                goto fail;
  64        }
  65
  66        res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
  67        if (!res) {
  68                dev_err(&pdev->dev, "no DMA resource\n");
  69                ret = -ENXIO;
  70                goto fail;
  71        }
  72
  73        davinci_vc->davinci_vcif.dma_tx_channel = res->start;
  74        davinci_vc->davinci_vcif.dma_tx_addr = fifo_base + DAVINCI_VC_WFIFO;
  75
  76        res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
  77        if (!res) {
  78                dev_err(&pdev->dev, "no DMA resource\n");
  79                ret = -ENXIO;
  80                goto fail;
  81        }
  82
  83        davinci_vc->davinci_vcif.dma_rx_channel = res->start;
  84        davinci_vc->davinci_vcif.dma_rx_addr = fifo_base + DAVINCI_VC_RFIFO;
  85
  86        davinci_vc->dev = &pdev->dev;
  87        davinci_vc->pdev = pdev;
  88
  89        /* Voice codec interface client */
  90        cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL];
  91        cell->name = "davinci-vcif";
  92        cell->platform_data = davinci_vc;
  93        cell->pdata_size = sizeof(*davinci_vc);
  94
  95        /* Voice codec CQ93VC client */
  96        cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL];
  97        cell->name = "cq93vc-codec";
  98        cell->platform_data = davinci_vc;
  99        cell->pdata_size = sizeof(*davinci_vc);
 100
 101        ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells,
 102                              DAVINCI_VC_CELLS, NULL, 0, NULL);
 103        if (ret != 0) {
 104                dev_err(&pdev->dev, "fail to register client devices\n");
 105                goto fail;
 106        }
 107
 108        return 0;
 109
 110fail:
 111        clk_disable(davinci_vc->clk);
 112
 113        return ret;
 114}
 115
 116static int davinci_vc_remove(struct platform_device *pdev)
 117{
 118        struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
 119
 120        mfd_remove_devices(&pdev->dev);
 121
 122        clk_disable(davinci_vc->clk);
 123
 124        return 0;
 125}
 126
 127static struct platform_driver davinci_vc_driver = {
 128        .driver = {
 129                .name = "davinci_voicecodec",
 130        },
 131        .remove = davinci_vc_remove,
 132};
 133
 134module_platform_driver_probe(davinci_vc_driver, davinci_vc_probe);
 135
 136MODULE_AUTHOR("Miguel Aguilar");
 137MODULE_DESCRIPTION("Texas Instruments DaVinci Voice Codec Core Interface");
 138MODULE_LICENSE("GPL");
 139