at v5.8-rc3 138 lines 3.3 kB view raw
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");