at v5.3-rc5 139 lines 3.4 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#include <mach/hardware.h> 23 24static const struct regmap_config davinci_vc_regmap = { 25 .reg_bits = 32, 26 .val_bits = 32, 27}; 28 29static int __init davinci_vc_probe(struct platform_device *pdev) 30{ 31 struct davinci_vc *davinci_vc; 32 struct resource *res; 33 struct mfd_cell *cell = NULL; 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 davinci_vc->base = devm_ioremap_resource(&pdev->dev, res); 52 if (IS_ERR(davinci_vc->base)) { 53 ret = PTR_ERR(davinci_vc->base); 54 goto fail; 55 } 56 57 davinci_vc->regmap = devm_regmap_init_mmio(&pdev->dev, 58 davinci_vc->base, 59 &davinci_vc_regmap); 60 if (IS_ERR(davinci_vc->regmap)) { 61 ret = PTR_ERR(davinci_vc->regmap); 62 goto fail; 63 } 64 65 res = platform_get_resource(pdev, IORESOURCE_DMA, 0); 66 if (!res) { 67 dev_err(&pdev->dev, "no DMA resource\n"); 68 ret = -ENXIO; 69 goto fail; 70 } 71 72 davinci_vc->davinci_vcif.dma_tx_channel = res->start; 73 davinci_vc->davinci_vcif.dma_tx_addr = 74 (dma_addr_t)(io_v2p(davinci_vc->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 = 85 (dma_addr_t)(io_v2p(davinci_vc->base) + DAVINCI_VC_RFIFO); 86 87 davinci_vc->dev = &pdev->dev; 88 davinci_vc->pdev = pdev; 89 90 /* Voice codec interface client */ 91 cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL]; 92 cell->name = "davinci-vcif"; 93 cell->platform_data = davinci_vc; 94 cell->pdata_size = sizeof(*davinci_vc); 95 96 /* Voice codec CQ93VC client */ 97 cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL]; 98 cell->name = "cq93vc-codec"; 99 cell->platform_data = davinci_vc; 100 cell->pdata_size = sizeof(*davinci_vc); 101 102 ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells, 103 DAVINCI_VC_CELLS, NULL, 0, NULL); 104 if (ret != 0) { 105 dev_err(&pdev->dev, "fail to register client devices\n"); 106 goto fail; 107 } 108 109 return 0; 110 111fail: 112 clk_disable(davinci_vc->clk); 113 114 return ret; 115} 116 117static int davinci_vc_remove(struct platform_device *pdev) 118{ 119 struct davinci_vc *davinci_vc = platform_get_drvdata(pdev); 120 121 mfd_remove_devices(&pdev->dev); 122 123 clk_disable(davinci_vc->clk); 124 125 return 0; 126} 127 128static struct platform_driver davinci_vc_driver = { 129 .driver = { 130 .name = "davinci_voicecodec", 131 }, 132 .remove = davinci_vc_remove, 133}; 134 135module_platform_driver_probe(davinci_vc_driver, davinci_vc_probe); 136 137MODULE_AUTHOR("Miguel Aguilar"); 138MODULE_DESCRIPTION("Texas Instruments DaVinci Voice Codec Core Interface"); 139MODULE_LICENSE("GPL");