| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
|---|
| 1 | 2 | /* |
|---|
| 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. |
|---|
| 3 | + * Copyright (c) 2010-2011,2013-2015,2020 The Linux Foundation. All rights reserved. |
|---|
| 12 | 4 | * |
|---|
| 13 | 5 | * lpass.h - Definitions for the QTi LPASS |
|---|
| 14 | 6 | */ |
|---|
| .. | .. |
|---|
| 20 | 12 | #include <linux/compiler.h> |
|---|
| 21 | 13 | #include <linux/platform_device.h> |
|---|
| 22 | 14 | #include <linux/regmap.h> |
|---|
| 15 | +#include <dt-bindings/sound/qcom,lpass.h> |
|---|
| 16 | +#include "lpass-hdmi.h" |
|---|
| 23 | 17 | |
|---|
| 24 | 18 | #define LPASS_AHBIX_CLOCK_FREQUENCY 131072000 |
|---|
| 25 | 19 | #define LPASS_MAX_MI2S_PORTS (8) |
|---|
| 26 | 20 | #define LPASS_MAX_DMA_CHANNELS (8) |
|---|
| 21 | +#define LPASS_MAX_HDMI_DMA_CHANNELS (4) |
|---|
| 22 | + |
|---|
| 23 | +#define QCOM_REGMAP_FIELD_ALLOC(d, m, f, mf) \ |
|---|
| 24 | + do { \ |
|---|
| 25 | + mf = devm_regmap_field_alloc(d, m, f); \ |
|---|
| 26 | + if (IS_ERR(mf)) \ |
|---|
| 27 | + return -EINVAL; \ |
|---|
| 28 | + } while (0) |
|---|
| 29 | + |
|---|
| 30 | +struct lpaif_i2sctl { |
|---|
| 31 | + struct regmap_field *loopback; |
|---|
| 32 | + struct regmap_field *spken; |
|---|
| 33 | + struct regmap_field *spkmode; |
|---|
| 34 | + struct regmap_field *spkmono; |
|---|
| 35 | + struct regmap_field *micen; |
|---|
| 36 | + struct regmap_field *micmode; |
|---|
| 37 | + struct regmap_field *micmono; |
|---|
| 38 | + struct regmap_field *wssrc; |
|---|
| 39 | + struct regmap_field *bitwidth; |
|---|
| 40 | +}; |
|---|
| 41 | + |
|---|
| 42 | + |
|---|
| 43 | +struct lpaif_dmactl { |
|---|
| 44 | + struct regmap_field *intf; |
|---|
| 45 | + struct regmap_field *bursten; |
|---|
| 46 | + struct regmap_field *wpscnt; |
|---|
| 47 | + struct regmap_field *fifowm; |
|---|
| 48 | + struct regmap_field *enable; |
|---|
| 49 | + struct regmap_field *dyncclk; |
|---|
| 50 | + struct regmap_field *burst8; |
|---|
| 51 | + struct regmap_field *burst16; |
|---|
| 52 | + struct regmap_field *dynburst; |
|---|
| 53 | +}; |
|---|
| 27 | 54 | |
|---|
| 28 | 55 | /* Both the CPU DAI and platform drivers will access this data */ |
|---|
| 29 | 56 | struct lpass_data { |
|---|
| .. | .. |
|---|
| 37 | 64 | /* MI2S bit clock (derived from system clock by a divider */ |
|---|
| 38 | 65 | struct clk *mi2s_bit_clk[LPASS_MAX_MI2S_PORTS]; |
|---|
| 39 | 66 | |
|---|
| 67 | + /* MI2S SD lines to use for playback/capture */ |
|---|
| 68 | + unsigned int mi2s_playback_sd_mode[LPASS_MAX_MI2S_PORTS]; |
|---|
| 69 | + unsigned int mi2s_capture_sd_mode[LPASS_MAX_MI2S_PORTS]; |
|---|
| 70 | + |
|---|
| 71 | + /* The state of MI2S prepare dai_ops was called */ |
|---|
| 72 | + bool mi2s_was_prepared[LPASS_MAX_MI2S_PORTS]; |
|---|
| 73 | + |
|---|
| 74 | + int hdmi_port_enable; |
|---|
| 75 | + |
|---|
| 40 | 76 | /* low-power audio interface (LPAIF) registers */ |
|---|
| 41 | 77 | void __iomem *lpaif; |
|---|
| 78 | + void __iomem *hdmiif; |
|---|
| 42 | 79 | |
|---|
| 43 | 80 | /* regmap backed by the low-power audio interface (LPAIF) registers */ |
|---|
| 44 | 81 | struct regmap *lpaif_map; |
|---|
| 82 | + struct regmap *hdmiif_map; |
|---|
| 45 | 83 | |
|---|
| 46 | 84 | /* interrupts from the low-power audio interface (LPAIF) */ |
|---|
| 47 | 85 | int lpaif_irq; |
|---|
| 48 | | - |
|---|
| 86 | + int hdmiif_irq; |
|---|
| 49 | 87 | /* SOC specific variations in the LPASS IP integration */ |
|---|
| 50 | 88 | struct lpass_variant *variant; |
|---|
| 51 | 89 | |
|---|
| 52 | 90 | /* bit map to keep track of static channel allocations */ |
|---|
| 53 | 91 | unsigned long dma_ch_bit_map; |
|---|
| 92 | + unsigned long hdmi_dma_ch_bit_map; |
|---|
| 54 | 93 | |
|---|
| 55 | 94 | /* used it for handling interrupt per dma channel */ |
|---|
| 56 | 95 | struct snd_pcm_substream *substream[LPASS_MAX_DMA_CHANNELS]; |
|---|
| 96 | + struct snd_pcm_substream *hdmi_substream[LPASS_MAX_HDMI_DMA_CHANNELS]; |
|---|
| 57 | 97 | |
|---|
| 58 | | - /* 8016 specific */ |
|---|
| 59 | | - struct clk *pcnoc_mport_clk; |
|---|
| 60 | | - struct clk *pcnoc_sway_clk; |
|---|
| 98 | + /* SOC specific clock list */ |
|---|
| 99 | + struct clk_bulk_data *clks; |
|---|
| 100 | + int num_clks; |
|---|
| 61 | 101 | |
|---|
| 102 | + /* Regmap fields of I2SCTL & DMACTL registers bitfields */ |
|---|
| 103 | + struct lpaif_i2sctl *i2sctl; |
|---|
| 104 | + struct lpaif_dmactl *rd_dmactl; |
|---|
| 105 | + struct lpaif_dmactl *wr_dmactl; |
|---|
| 106 | + struct lpaif_dmactl *hdmi_rd_dmactl; |
|---|
| 107 | + /* Regmap fields of HDMI_CTRL registers*/ |
|---|
| 108 | + struct regmap_field *hdmitx_legacy_en; |
|---|
| 109 | + struct regmap_field *hdmitx_parity_calc_en; |
|---|
| 110 | + struct regmap_field *hdmitx_ch_msb[LPASS_MAX_HDMI_DMA_CHANNELS]; |
|---|
| 111 | + struct regmap_field *hdmitx_ch_lsb[LPASS_MAX_HDMI_DMA_CHANNELS]; |
|---|
| 112 | + struct lpass_hdmi_tx_ctl *tx_ctl; |
|---|
| 113 | + struct lpass_vbit_ctrl *vbit_ctl; |
|---|
| 114 | + struct lpass_hdmitx_dmactl *hdmi_tx_dmactl[LPASS_MAX_HDMI_DMA_CHANNELS]; |
|---|
| 115 | + struct lpass_dp_metadata_ctl *meta_ctl; |
|---|
| 116 | + struct lpass_sstream_ctl *sstream_ctl; |
|---|
| 62 | 117 | }; |
|---|
| 63 | 118 | |
|---|
| 64 | 119 | /* Vairant data per each SOC */ |
|---|
| 65 | 120 | struct lpass_variant { |
|---|
| 66 | | - u32 i2sctrl_reg_base; |
|---|
| 67 | | - u32 i2sctrl_reg_stride; |
|---|
| 68 | | - u32 i2s_ports; |
|---|
| 69 | 121 | u32 irq_reg_base; |
|---|
| 70 | 122 | u32 irq_reg_stride; |
|---|
| 71 | 123 | u32 irq_ports; |
|---|
| 72 | 124 | u32 rdma_reg_base; |
|---|
| 73 | 125 | u32 rdma_reg_stride; |
|---|
| 74 | 126 | u32 rdma_channels; |
|---|
| 127 | + u32 hdmi_rdma_reg_base; |
|---|
| 128 | + u32 hdmi_rdma_reg_stride; |
|---|
| 129 | + u32 hdmi_rdma_channels; |
|---|
| 75 | 130 | u32 wrdma_reg_base; |
|---|
| 76 | 131 | u32 wrdma_reg_stride; |
|---|
| 77 | 132 | u32 wrdma_channels; |
|---|
| 133 | + u32 i2sctrl_reg_base; |
|---|
| 134 | + u32 i2sctrl_reg_stride; |
|---|
| 135 | + u32 i2s_ports; |
|---|
| 136 | + |
|---|
| 137 | + /* I2SCTL Register fields */ |
|---|
| 138 | + struct reg_field loopback; |
|---|
| 139 | + struct reg_field spken; |
|---|
| 140 | + struct reg_field spkmode; |
|---|
| 141 | + struct reg_field spkmono; |
|---|
| 142 | + struct reg_field micen; |
|---|
| 143 | + struct reg_field micmode; |
|---|
| 144 | + struct reg_field micmono; |
|---|
| 145 | + struct reg_field wssrc; |
|---|
| 146 | + struct reg_field bitwidth; |
|---|
| 147 | + |
|---|
| 148 | + u32 hdmi_irq_reg_base; |
|---|
| 149 | + u32 hdmi_irq_reg_stride; |
|---|
| 150 | + u32 hdmi_irq_ports; |
|---|
| 151 | + |
|---|
| 152 | + /* HDMI specific controls */ |
|---|
| 153 | + u32 hdmi_tx_ctl_addr; |
|---|
| 154 | + u32 hdmi_legacy_addr; |
|---|
| 155 | + u32 hdmi_vbit_addr; |
|---|
| 156 | + u32 hdmi_ch_lsb_addr; |
|---|
| 157 | + u32 hdmi_ch_msb_addr; |
|---|
| 158 | + u32 ch_stride; |
|---|
| 159 | + u32 hdmi_parity_addr; |
|---|
| 160 | + u32 hdmi_dmactl_addr; |
|---|
| 161 | + u32 hdmi_dma_stride; |
|---|
| 162 | + u32 hdmi_DP_addr; |
|---|
| 163 | + u32 hdmi_sstream_addr; |
|---|
| 164 | + |
|---|
| 165 | + /* HDMI SSTREAM CTRL fields */ |
|---|
| 166 | + struct reg_field sstream_en; |
|---|
| 167 | + struct reg_field dma_sel; |
|---|
| 168 | + struct reg_field auto_bbit_en; |
|---|
| 169 | + struct reg_field layout; |
|---|
| 170 | + struct reg_field layout_sp; |
|---|
| 171 | + struct reg_field set_sp_on_en; |
|---|
| 172 | + struct reg_field dp_audio; |
|---|
| 173 | + struct reg_field dp_staffing_en; |
|---|
| 174 | + struct reg_field dp_sp_b_hw_en; |
|---|
| 175 | + |
|---|
| 176 | + /* HDMI DP METADATA CTL fields */ |
|---|
| 177 | + struct reg_field mute; |
|---|
| 178 | + struct reg_field as_sdp_cc; |
|---|
| 179 | + struct reg_field as_sdp_ct; |
|---|
| 180 | + struct reg_field aif_db4; |
|---|
| 181 | + struct reg_field frequency; |
|---|
| 182 | + struct reg_field mst_index; |
|---|
| 183 | + struct reg_field dptx_index; |
|---|
| 184 | + |
|---|
| 185 | + /* HDMI TX CTRL fields */ |
|---|
| 186 | + struct reg_field soft_reset; |
|---|
| 187 | + struct reg_field force_reset; |
|---|
| 188 | + |
|---|
| 189 | + /* HDMI TX DMA CTRL */ |
|---|
| 190 | + struct reg_field use_hw_chs; |
|---|
| 191 | + struct reg_field use_hw_usr; |
|---|
| 192 | + struct reg_field hw_chs_sel; |
|---|
| 193 | + struct reg_field hw_usr_sel; |
|---|
| 194 | + |
|---|
| 195 | + /* HDMI VBIT CTRL */ |
|---|
| 196 | + struct reg_field replace_vbit; |
|---|
| 197 | + struct reg_field vbit_stream; |
|---|
| 198 | + |
|---|
| 199 | + /* HDMI TX LEGACY */ |
|---|
| 200 | + struct reg_field legacy_en; |
|---|
| 201 | + |
|---|
| 202 | + /* HDMI TX PARITY */ |
|---|
| 203 | + struct reg_field calc_en; |
|---|
| 204 | + |
|---|
| 205 | + /* HDMI CH LSB */ |
|---|
| 206 | + struct reg_field lsb_bits; |
|---|
| 207 | + |
|---|
| 208 | + /* HDMI CH MSB */ |
|---|
| 209 | + struct reg_field msb_bits; |
|---|
| 210 | + |
|---|
| 211 | + struct reg_field hdmi_rdma_bursten; |
|---|
| 212 | + struct reg_field hdmi_rdma_wpscnt; |
|---|
| 213 | + struct reg_field hdmi_rdma_fifowm; |
|---|
| 214 | + struct reg_field hdmi_rdma_enable; |
|---|
| 215 | + struct reg_field hdmi_rdma_dyncclk; |
|---|
| 216 | + struct reg_field hdmi_rdma_burst8; |
|---|
| 217 | + struct reg_field hdmi_rdma_burst16; |
|---|
| 218 | + struct reg_field hdmi_rdma_dynburst; |
|---|
| 219 | + |
|---|
| 220 | + /* RD_DMA Register fields */ |
|---|
| 221 | + struct reg_field rdma_intf; |
|---|
| 222 | + struct reg_field rdma_bursten; |
|---|
| 223 | + struct reg_field rdma_wpscnt; |
|---|
| 224 | + struct reg_field rdma_fifowm; |
|---|
| 225 | + struct reg_field rdma_enable; |
|---|
| 226 | + struct reg_field rdma_dyncclk; |
|---|
| 227 | + |
|---|
| 228 | + /* WR_DMA Register fields */ |
|---|
| 229 | + struct reg_field wrdma_intf; |
|---|
| 230 | + struct reg_field wrdma_bursten; |
|---|
| 231 | + struct reg_field wrdma_wpscnt; |
|---|
| 232 | + struct reg_field wrdma_fifowm; |
|---|
| 233 | + struct reg_field wrdma_enable; |
|---|
| 234 | + struct reg_field wrdma_dyncclk; |
|---|
| 78 | 235 | |
|---|
| 79 | 236 | /** |
|---|
| 80 | 237 | * on SOCs like APQ8016 the channel control bits start |
|---|
| .. | .. |
|---|
| 85 | 242 | /* SOC specific initialization like clocks */ |
|---|
| 86 | 243 | int (*init)(struct platform_device *pdev); |
|---|
| 87 | 244 | int (*exit)(struct platform_device *pdev); |
|---|
| 88 | | - int (*alloc_dma_channel)(struct lpass_data *data, int direction); |
|---|
| 89 | | - int (*free_dma_channel)(struct lpass_data *data, int ch); |
|---|
| 245 | + int (*alloc_dma_channel)(struct lpass_data *data, int direction, unsigned int dai_id); |
|---|
| 246 | + int (*free_dma_channel)(struct lpass_data *data, int ch, unsigned int dai_id); |
|---|
| 90 | 247 | |
|---|
| 91 | 248 | /* SOC specific dais */ |
|---|
| 92 | 249 | struct snd_soc_dai_driver *dai_driver; |
|---|
| 93 | 250 | int num_dai; |
|---|
| 94 | 251 | const char * const *dai_osr_clk_names; |
|---|
| 95 | 252 | const char * const *dai_bit_clk_names; |
|---|
| 253 | + |
|---|
| 254 | + /* SOC specific clocks configuration */ |
|---|
| 255 | + const char **clk_name; |
|---|
| 256 | + int num_clks; |
|---|
| 96 | 257 | }; |
|---|
| 97 | 258 | |
|---|
| 98 | 259 | /* register the platform driver from the CPU DAI driver */ |
|---|