1 /* 2 * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 and 6 * only version 2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * lpass-ipq806x.c -- ALSA SoC CPU DAI driver for QTi LPASS 14 * Splited out the IPQ8064 soc specific from lpass-cpu.c 15 */ 16 17 #include <linux/clk.h> 18 #include <linux/device.h> 19 #include <linux/err.h> 20 #include <linux/kernel.h> 21 #include <linux/module.h> 22 #include <linux/of.h> 23 #include <linux/platform_device.h> 24 #include <sound/pcm.h> 25 #include <sound/soc.h> 26 #include <sound/soc-dai.h> 27 28 #include "lpass-lpaif-reg.h" 29 #include "lpass.h" 30 31 enum lpaif_i2s_ports { 32 IPQ806X_LPAIF_I2S_PORT_CODEC_SPK, 33 IPQ806X_LPAIF_I2S_PORT_CODEC_MIC, 34 IPQ806X_LPAIF_I2S_PORT_SEC_SPK, 35 IPQ806X_LPAIF_I2S_PORT_SEC_MIC, 36 IPQ806X_LPAIF_I2S_PORT_MI2S, 37 }; 38 39 enum lpaif_dma_channels { 40 IPQ806X_LPAIF_RDMA_CHAN_MI2S, 41 IPQ806X_LPAIF_RDMA_CHAN_PCM0, 42 IPQ806X_LPAIF_RDMA_CHAN_PCM1, 43 }; 44 45 static struct snd_soc_dai_driver ipq806x_lpass_cpu_dai_driver = { 46 .id = IPQ806X_LPAIF_I2S_PORT_MI2S, 47 .playback = { 48 .stream_name = "lpass-cpu-playback", 49 .formats = SNDRV_PCM_FMTBIT_S16 | 50 SNDRV_PCM_FMTBIT_S24 | 51 SNDRV_PCM_FMTBIT_S32, 52 .rates = SNDRV_PCM_RATE_8000 | 53 SNDRV_PCM_RATE_16000 | 54 SNDRV_PCM_RATE_32000 | 55 SNDRV_PCM_RATE_48000 | 56 SNDRV_PCM_RATE_96000, 57 .rate_min = 8000, 58 .rate_max = 96000, 59 .channels_min = 1, 60 .channels_max = 8, 61 }, 62 .probe = &asoc_qcom_lpass_cpu_dai_probe, 63 .ops = &asoc_qcom_lpass_cpu_dai_ops, 64 }; 65 66 static int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata, int dir) 67 { 68 if (dir == SNDRV_PCM_STREAM_PLAYBACK) 69 return IPQ806X_LPAIF_RDMA_CHAN_MI2S; 70 else /* Capture currently not implemented */ 71 return -EINVAL; 72 } 73 74 static int ipq806x_lpass_free_dma_channel(struct lpass_data *drvdata, int chan) 75 { 76 return 0; 77 } 78 79 static struct lpass_variant ipq806x_data = { 80 .i2sctrl_reg_base = 0x0010, 81 .i2sctrl_reg_stride = 0x04, 82 .i2s_ports = 5, 83 .irq_reg_base = 0x3000, 84 .irq_reg_stride = 0x1000, 85 .irq_ports = 3, 86 .rdma_reg_base = 0x6000, 87 .rdma_reg_stride = 0x1000, 88 .rdma_channels = 4, 89 .wrdma_reg_base = 0xB000, 90 .wrdma_reg_stride = 0x1000, 91 .wrdma_channel_start = 5, 92 .wrdma_channels = 4, 93 .dai_driver = &ipq806x_lpass_cpu_dai_driver, 94 .num_dai = 1, 95 .dai_osr_clk_names = (const char *[]) { 96 "mi2s-osr-clk", 97 }, 98 .dai_bit_clk_names = (const char *[]) { 99 "mi2s-bit-clk", 100 }, 101 .alloc_dma_channel = ipq806x_lpass_alloc_dma_channel, 102 .free_dma_channel = ipq806x_lpass_free_dma_channel, 103 }; 104 105 static const struct of_device_id ipq806x_lpass_cpu_device_id[] = { 106 { .compatible = "qcom,lpass-cpu", .data = &ipq806x_data }, 107 {} 108 }; 109 MODULE_DEVICE_TABLE(of, ipq806x_lpass_cpu_device_id); 110 111 static struct platform_driver ipq806x_lpass_cpu_platform_driver = { 112 .driver = { 113 .name = "lpass-cpu", 114 .of_match_table = of_match_ptr(ipq806x_lpass_cpu_device_id), 115 }, 116 .probe = asoc_qcom_lpass_cpu_platform_probe, 117 .remove = asoc_qcom_lpass_cpu_platform_remove, 118 }; 119 module_platform_driver(ipq806x_lpass_cpu_platform_driver); 120 121 MODULE_DESCRIPTION("QTi LPASS CPU Driver"); 122 MODULE_LICENSE("GPL v2"); 123