cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

lpass-sc7180.c (9001B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
      4 *
      5 * lpass-sc7180.c -- ALSA SoC platform-machine driver for QTi LPASS
      6 */
      7
      8#include <linux/clk.h>
      9#include <linux/device.h>
     10#include <linux/err.h>
     11#include <linux/kernel.h>
     12#include <linux/module.h>
     13#include <linux/of.h>
     14#include <linux/platform_device.h>
     15#include <dt-bindings/sound/sc7180-lpass.h>
     16#include <sound/pcm.h>
     17#include <sound/soc.h>
     18
     19#include "lpass-lpaif-reg.h"
     20#include "lpass.h"
     21
     22static struct snd_soc_dai_driver sc7180_lpass_cpu_dai_driver[] = {
     23	{
     24		.id = MI2S_PRIMARY,
     25		.name = "Primary MI2S",
     26		.playback = {
     27			.stream_name = "Primary Playback",
     28			.formats	= SNDRV_PCM_FMTBIT_S16,
     29			.rates = SNDRV_PCM_RATE_48000,
     30			.rate_min	= 48000,
     31			.rate_max	= 48000,
     32			.channels_min	= 2,
     33			.channels_max	= 2,
     34		},
     35		.capture = {
     36			.stream_name = "Primary Capture",
     37			.formats = SNDRV_PCM_FMTBIT_S16 |
     38				SNDRV_PCM_FMTBIT_S32,
     39			.rates = SNDRV_PCM_RATE_48000,
     40			.rate_min	= 48000,
     41			.rate_max	= 48000,
     42			.channels_min	= 2,
     43			.channels_max	= 2,
     44		},
     45		.probe	= &asoc_qcom_lpass_cpu_dai_probe,
     46		.ops    = &asoc_qcom_lpass_cpu_dai_ops,
     47	}, {
     48		.id = MI2S_SECONDARY,
     49		.name = "Secondary MI2S",
     50		.playback = {
     51			.stream_name = "Secondary Playback",
     52			.formats	= SNDRV_PCM_FMTBIT_S16,
     53			.rates = SNDRV_PCM_RATE_48000,
     54			.rate_min	= 48000,
     55			.rate_max	= 48000,
     56			.channels_min	= 2,
     57			.channels_max	= 2,
     58		},
     59		.probe	= &asoc_qcom_lpass_cpu_dai_probe,
     60		.ops    = &asoc_qcom_lpass_cpu_dai_ops,
     61		.pcm_new = lpass_cpu_pcm_new,
     62	}, {
     63		.id = LPASS_DP_RX,
     64		.name = "Hdmi",
     65		.playback = {
     66			.stream_name = "Hdmi Playback",
     67			.formats	= SNDRV_PCM_FMTBIT_S24,
     68			.rates = SNDRV_PCM_RATE_48000,
     69			.rate_min	= 48000,
     70			.rate_max	= 48000,
     71			.channels_min	= 2,
     72			.channels_max	= 2,
     73		},
     74		.ops    = &asoc_qcom_lpass_hdmi_dai_ops,
     75	},
     76};
     77
     78static int sc7180_lpass_alloc_dma_channel(struct lpass_data *drvdata,
     79					   int direction, unsigned int dai_id)
     80{
     81	struct lpass_variant *v = drvdata->variant;
     82	int chan = 0;
     83
     84	if (dai_id == LPASS_DP_RX) {
     85		if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
     86			chan = find_first_zero_bit(&drvdata->hdmi_dma_ch_bit_map,
     87						v->hdmi_rdma_channels);
     88
     89			if (chan >= v->hdmi_rdma_channels)
     90				return -EBUSY;
     91		}
     92		set_bit(chan, &drvdata->hdmi_dma_ch_bit_map);
     93	} else {
     94		if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
     95			chan = find_first_zero_bit(&drvdata->dma_ch_bit_map,
     96						v->rdma_channels);
     97
     98			if (chan >= v->rdma_channels)
     99				return -EBUSY;
    100		} else {
    101			chan = find_next_zero_bit(&drvdata->dma_ch_bit_map,
    102					v->wrdma_channel_start +
    103					v->wrdma_channels,
    104					v->wrdma_channel_start);
    105
    106			if (chan >=  v->wrdma_channel_start + v->wrdma_channels)
    107				return -EBUSY;
    108		}
    109
    110		set_bit(chan, &drvdata->dma_ch_bit_map);
    111	}
    112	return chan;
    113}
    114
    115static int sc7180_lpass_free_dma_channel(struct lpass_data *drvdata, int chan, unsigned int dai_id)
    116{
    117	if (dai_id == LPASS_DP_RX)
    118		clear_bit(chan, &drvdata->hdmi_dma_ch_bit_map);
    119	else
    120		clear_bit(chan, &drvdata->dma_ch_bit_map);
    121
    122	return 0;
    123}
    124
    125static int sc7180_lpass_init(struct platform_device *pdev)
    126{
    127	struct lpass_data *drvdata = platform_get_drvdata(pdev);
    128	struct lpass_variant *variant = drvdata->variant;
    129	struct device *dev = &pdev->dev;
    130	int ret, i;
    131
    132	drvdata->clks = devm_kcalloc(dev, variant->num_clks,
    133				     sizeof(*drvdata->clks), GFP_KERNEL);
    134	drvdata->num_clks = variant->num_clks;
    135
    136	for (i = 0; i < drvdata->num_clks; i++)
    137		drvdata->clks[i].id = variant->clk_name[i];
    138
    139	ret = devm_clk_bulk_get(dev, drvdata->num_clks, drvdata->clks);
    140	if (ret) {
    141		dev_err(dev, "Failed to get clocks %d\n", ret);
    142		return ret;
    143	}
    144
    145	ret = clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks);
    146	if (ret) {
    147		dev_err(dev, "sc7180 clk_enable failed\n");
    148		return ret;
    149	}
    150
    151	return 0;
    152}
    153
    154static int sc7180_lpass_exit(struct platform_device *pdev)
    155{
    156	struct lpass_data *drvdata = platform_get_drvdata(pdev);
    157
    158	clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks);
    159
    160	return 0;
    161}
    162
    163static struct lpass_variant sc7180_data = {
    164	.i2sctrl_reg_base	= 0x1000,
    165	.i2sctrl_reg_stride	= 0x1000,
    166	.i2s_ports		= 3,
    167	.irq_reg_base		= 0x9000,
    168	.irq_reg_stride		= 0x1000,
    169	.irq_ports		= 3,
    170	.rdma_reg_base		= 0xC000,
    171	.rdma_reg_stride	= 0x1000,
    172	.rdma_channels		= 5,
    173	.hdmi_rdma_reg_base		= 0x64000,
    174	.hdmi_rdma_reg_stride	= 0x1000,
    175	.hdmi_rdma_channels		= 4,
    176	.dmactl_audif_start	= 1,
    177	.wrdma_reg_base		= 0x18000,
    178	.wrdma_reg_stride	= 0x1000,
    179	.wrdma_channel_start	= 5,
    180	.wrdma_channels		= 4,
    181
    182	.loopback		= REG_FIELD_ID(0x1000, 17, 17, 3, 0x1000),
    183	.spken			= REG_FIELD_ID(0x1000, 16, 16, 3, 0x1000),
    184	.spkmode		= REG_FIELD_ID(0x1000, 11, 15, 3, 0x1000),
    185	.spkmono		= REG_FIELD_ID(0x1000, 10, 10, 3, 0x1000),
    186	.micen			= REG_FIELD_ID(0x1000, 9, 9, 3, 0x1000),
    187	.micmode		= REG_FIELD_ID(0x1000, 4, 8, 3, 0x1000),
    188	.micmono		= REG_FIELD_ID(0x1000, 3, 3, 3, 0x1000),
    189	.wssrc			= REG_FIELD_ID(0x1000, 2, 2, 3, 0x1000),
    190	.bitwidth		= REG_FIELD_ID(0x1000, 0, 1, 3, 0x1000),
    191
    192	.rdma_dyncclk		= REG_FIELD_ID(0xC000, 21, 21, 5, 0x1000),
    193	.rdma_bursten		= REG_FIELD_ID(0xC000, 20, 20, 5, 0x1000),
    194	.rdma_wpscnt		= REG_FIELD_ID(0xC000, 16, 19, 5, 0x1000),
    195	.rdma_intf			= REG_FIELD_ID(0xC000, 12, 15, 5, 0x1000),
    196	.rdma_fifowm		= REG_FIELD_ID(0xC000, 1, 5, 5, 0x1000),
    197	.rdma_enable		= REG_FIELD_ID(0xC000, 0, 0, 5, 0x1000),
    198
    199	.wrdma_dyncclk		= REG_FIELD_ID(0x18000, 22, 22, 4, 0x1000),
    200	.wrdma_bursten		= REG_FIELD_ID(0x18000, 21, 21, 4, 0x1000),
    201	.wrdma_wpscnt		= REG_FIELD_ID(0x18000, 17, 20, 4, 0x1000),
    202	.wrdma_intf		= REG_FIELD_ID(0x18000, 12, 16, 4, 0x1000),
    203	.wrdma_fifowm		= REG_FIELD_ID(0x18000, 1, 5, 4, 0x1000),
    204	.wrdma_enable		= REG_FIELD_ID(0x18000, 0, 0, 4, 0x1000),
    205
    206	.hdmi_tx_ctl_addr	= 0x1000,
    207	.hdmi_legacy_addr	= 0x1008,
    208	.hdmi_vbit_addr		= 0x610c0,
    209	.hdmi_ch_lsb_addr	= 0x61048,
    210	.hdmi_ch_msb_addr	= 0x6104c,
    211	.ch_stride		= 0x8,
    212	.hdmi_parity_addr	= 0x61034,
    213	.hdmi_dmactl_addr	= 0x61038,
    214	.hdmi_dma_stride	= 0x4,
    215	.hdmi_DP_addr		= 0x610c8,
    216	.hdmi_sstream_addr	= 0x6101c,
    217	.hdmi_irq_reg_base		= 0x63000,
    218	.hdmi_irq_ports		= 1,
    219
    220	.hdmi_rdma_dyncclk		= REG_FIELD_ID(0x64000, 14, 14, 4, 0x1000),
    221	.hdmi_rdma_bursten		= REG_FIELD_ID(0x64000, 13, 13, 4, 0x1000),
    222	.hdmi_rdma_burst8		= REG_FIELD_ID(0x64000, 15, 15, 4, 0x1000),
    223	.hdmi_rdma_burst16		= REG_FIELD_ID(0x64000, 16, 16, 4, 0x1000),
    224	.hdmi_rdma_dynburst		= REG_FIELD_ID(0x64000, 18, 18, 4, 0x1000),
    225	.hdmi_rdma_wpscnt		= REG_FIELD_ID(0x64000, 10, 12, 4, 0x1000),
    226	.hdmi_rdma_fifowm		= REG_FIELD_ID(0x64000, 1, 5, 4, 0x1000),
    227	.hdmi_rdma_enable		= REG_FIELD_ID(0x64000, 0, 0, 4, 0x1000),
    228
    229	.sstream_en		= REG_FIELD(0x6101c, 0, 0),
    230	.dma_sel			= REG_FIELD(0x6101c, 1, 2),
    231	.auto_bbit_en	= REG_FIELD(0x6101c, 3, 3),
    232	.layout			= REG_FIELD(0x6101c, 4, 4),
    233	.layout_sp		= REG_FIELD(0x6101c, 5, 8),
    234	.set_sp_on_en	= REG_FIELD(0x6101c, 10, 10),
    235	.dp_audio		= REG_FIELD(0x6101c, 11, 11),
    236	.dp_staffing_en	= REG_FIELD(0x6101c, 12, 12),
    237	.dp_sp_b_hw_en	= REG_FIELD(0x6101c, 13, 13),
    238
    239	.mute			= REG_FIELD(0x610c8, 0, 0),
    240	.as_sdp_cc		= REG_FIELD(0x610c8, 1, 3),
    241	.as_sdp_ct		= REG_FIELD(0x610c8, 4, 7),
    242	.aif_db4			= REG_FIELD(0x610c8, 8, 15),
    243	.frequency		= REG_FIELD(0x610c8, 16, 21),
    244	.mst_index		= REG_FIELD(0x610c8, 28, 29),
    245	.dptx_index		= REG_FIELD(0x610c8, 30, 31),
    246
    247	.soft_reset		= REG_FIELD(0x1000, 31, 31),
    248	.force_reset	= REG_FIELD(0x1000, 30, 30),
    249
    250	.use_hw_chs		= REG_FIELD(0x61038, 0, 0),
    251	.use_hw_usr		= REG_FIELD(0x61038, 1, 1),
    252	.hw_chs_sel		= REG_FIELD(0x61038, 2, 4),
    253	.hw_usr_sel		= REG_FIELD(0x61038, 5, 6),
    254
    255	.replace_vbit	= REG_FIELD(0x610c0, 0, 0),
    256	.vbit_stream	= REG_FIELD(0x610c0, 1, 1),
    257
    258	.legacy_en		=  REG_FIELD(0x1008, 0, 0),
    259	.calc_en		=  REG_FIELD(0x61034, 0, 0),
    260	.lsb_bits		=  REG_FIELD(0x61048, 0, 31),
    261	.msb_bits		=  REG_FIELD(0x6104c, 0, 31),
    262
    263
    264	.clk_name		= (const char*[]) {
    265				   "pcnoc-sway-clk",
    266				   "audio-core",
    267				   "pcnoc-mport-clk",
    268				},
    269	.num_clks		= 3,
    270	.dai_driver		= sc7180_lpass_cpu_dai_driver,
    271	.num_dai		= ARRAY_SIZE(sc7180_lpass_cpu_dai_driver),
    272	.dai_osr_clk_names      = (const char *[]) {
    273				   "mclk0",
    274				   "null",
    275				},
    276	.dai_bit_clk_names      = (const char *[]) {
    277				   "mi2s-bit-clk0",
    278				   "mi2s-bit-clk1",
    279				},
    280	.init			= sc7180_lpass_init,
    281	.exit			= sc7180_lpass_exit,
    282	.alloc_dma_channel	= sc7180_lpass_alloc_dma_channel,
    283	.free_dma_channel	= sc7180_lpass_free_dma_channel,
    284};
    285
    286static const struct of_device_id sc7180_lpass_cpu_device_id[] __maybe_unused = {
    287	{.compatible = "qcom,sc7180-lpass-cpu", .data = &sc7180_data},
    288	{}
    289};
    290MODULE_DEVICE_TABLE(of, sc7180_lpass_cpu_device_id);
    291
    292static struct platform_driver sc7180_lpass_cpu_platform_driver = {
    293	.driver = {
    294		.name = "sc7180-lpass-cpu",
    295		.of_match_table = of_match_ptr(sc7180_lpass_cpu_device_id),
    296	},
    297	.probe = asoc_qcom_lpass_cpu_platform_probe,
    298	.remove = asoc_qcom_lpass_cpu_platform_remove,
    299	.shutdown = asoc_qcom_lpass_cpu_platform_shutdown,
    300};
    301
    302module_platform_driver(sc7180_lpass_cpu_platform_driver);
    303
    304MODULE_DESCRIPTION("SC7180 LPASS CPU DRIVER");
    305MODULE_LICENSE("GPL v2");