Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (c) 2021, Linaro Limited
0003 
0004 #include <linux/module.h>
0005 #include <linux/slab.h>
0006 #include <linux/platform_device.h>
0007 #include <linux/device.h>
0008 #include <linux/kernel.h>
0009 #include <linux/component.h>
0010 #include <linux/pm_runtime.h>
0011 #include <linux/irq.h>
0012 #include <linux/irqdomain.h>
0013 #include <linux/of.h>
0014 #include <linux/soundwire/sdw.h>
0015 #include <linux/soundwire/sdw_type.h>
0016 #include <linux/soundwire/sdw_registers.h>
0017 #include <linux/regmap.h>
0018 #include <sound/soc.h>
0019 #include <sound/soc-dapm.h>
0020 #include "wcd938x.h"
0021 
0022 #define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m) (0xE0 + 0x10 * (m))
0023 
0024 static struct wcd938x_sdw_ch_info wcd938x_sdw_rx_ch_info[] = {
0025     WCD_SDW_CH(WCD938X_HPH_L, WCD938X_HPH_PORT, BIT(0)),
0026     WCD_SDW_CH(WCD938X_HPH_R, WCD938X_HPH_PORT, BIT(1)),
0027     WCD_SDW_CH(WCD938X_CLSH, WCD938X_CLSH_PORT, BIT(0)),
0028     WCD_SDW_CH(WCD938X_COMP_L, WCD938X_COMP_PORT, BIT(0)),
0029     WCD_SDW_CH(WCD938X_COMP_R, WCD938X_COMP_PORT, BIT(1)),
0030     WCD_SDW_CH(WCD938X_LO, WCD938X_LO_PORT, BIT(0)),
0031     WCD_SDW_CH(WCD938X_DSD_L, WCD938X_DSD_PORT, BIT(0)),
0032     WCD_SDW_CH(WCD938X_DSD_R, WCD938X_DSD_PORT, BIT(1)),
0033 };
0034 
0035 static struct wcd938x_sdw_ch_info wcd938x_sdw_tx_ch_info[] = {
0036     WCD_SDW_CH(WCD938X_ADC1, WCD938X_ADC_1_2_PORT, BIT(0)),
0037     WCD_SDW_CH(WCD938X_ADC2, WCD938X_ADC_1_2_PORT, BIT(1)),
0038     WCD_SDW_CH(WCD938X_ADC3, WCD938X_ADC_3_4_PORT, BIT(0)),
0039     WCD_SDW_CH(WCD938X_ADC4, WCD938X_ADC_3_4_PORT, BIT(1)),
0040     WCD_SDW_CH(WCD938X_DMIC0, WCD938X_DMIC_0_3_MBHC_PORT, BIT(0)),
0041     WCD_SDW_CH(WCD938X_DMIC1, WCD938X_DMIC_0_3_MBHC_PORT, BIT(1)),
0042     WCD_SDW_CH(WCD938X_MBHC, WCD938X_DMIC_0_3_MBHC_PORT, BIT(2)),
0043     WCD_SDW_CH(WCD938X_DMIC2, WCD938X_DMIC_0_3_MBHC_PORT, BIT(2)),
0044     WCD_SDW_CH(WCD938X_DMIC3, WCD938X_DMIC_0_3_MBHC_PORT, BIT(3)),
0045     WCD_SDW_CH(WCD938X_DMIC4, WCD938X_DMIC_4_7_PORT, BIT(0)),
0046     WCD_SDW_CH(WCD938X_DMIC5, WCD938X_DMIC_4_7_PORT, BIT(1)),
0047     WCD_SDW_CH(WCD938X_DMIC6, WCD938X_DMIC_4_7_PORT, BIT(2)),
0048     WCD_SDW_CH(WCD938X_DMIC7, WCD938X_DMIC_4_7_PORT, BIT(3)),
0049 };
0050 
0051 static struct sdw_dpn_prop wcd938x_dpn_prop[WCD938X_MAX_SWR_PORTS] = {
0052     {
0053         .num = 1,
0054         .type = SDW_DPN_SIMPLE,
0055         .min_ch = 1,
0056         .max_ch = 8,
0057         .simple_ch_prep_sm = true,
0058     }, {
0059         .num = 2,
0060         .type = SDW_DPN_SIMPLE,
0061         .min_ch = 1,
0062         .max_ch = 4,
0063         .simple_ch_prep_sm = true,
0064     }, {
0065         .num = 3,
0066         .type = SDW_DPN_SIMPLE,
0067         .min_ch = 1,
0068         .max_ch = 4,
0069         .simple_ch_prep_sm = true,
0070     }, {
0071         .num = 4,
0072         .type = SDW_DPN_SIMPLE,
0073         .min_ch = 1,
0074         .max_ch = 4,
0075         .simple_ch_prep_sm = true,
0076     }, {
0077         .num = 5,
0078         .type = SDW_DPN_SIMPLE,
0079         .min_ch = 1,
0080         .max_ch = 4,
0081         .simple_ch_prep_sm = true,
0082     }
0083 };
0084 
0085 struct device *wcd938x_sdw_device_get(struct device_node *np)
0086 {
0087     return bus_find_device_by_of_node(&sdw_bus_type, np);
0088 
0089 }
0090 EXPORT_SYMBOL_GPL(wcd938x_sdw_device_get);
0091 
0092 int wcd938x_swr_get_current_bank(struct sdw_slave *sdev)
0093 {
0094     int bank;
0095 
0096     bank  = sdw_read(sdev, SDW_SCP_CTRL);
0097 
0098     return ((bank & 0x40) ? 1 : 0);
0099 }
0100 EXPORT_SYMBOL_GPL(wcd938x_swr_get_current_bank);
0101 
0102 int wcd938x_sdw_hw_params(struct wcd938x_sdw_priv *wcd,
0103               struct snd_pcm_substream *substream,
0104               struct snd_pcm_hw_params *params,
0105               struct snd_soc_dai *dai)
0106 {
0107     struct sdw_port_config port_config[WCD938X_MAX_SWR_PORTS];
0108     unsigned long ch_mask;
0109     int i, j;
0110 
0111     wcd->sconfig.ch_count = 1;
0112     wcd->active_ports = 0;
0113     for (i = 0; i < WCD938X_MAX_SWR_PORTS; i++) {
0114         ch_mask = wcd->port_config[i].ch_mask;
0115 
0116         if (!ch_mask)
0117             continue;
0118 
0119         for_each_set_bit(j, &ch_mask, 4)
0120             wcd->sconfig.ch_count++;
0121 
0122         port_config[wcd->active_ports] = wcd->port_config[i];
0123         wcd->active_ports++;
0124     }
0125 
0126     wcd->sconfig.bps = 1;
0127     wcd->sconfig.frame_rate =  params_rate(params);
0128     if (wcd->is_tx)
0129         wcd->sconfig.direction = SDW_DATA_DIR_TX;
0130     else
0131         wcd->sconfig.direction = SDW_DATA_DIR_RX;
0132 
0133     wcd->sconfig.type = SDW_STREAM_PCM;
0134 
0135     return sdw_stream_add_slave(wcd->sdev, &wcd->sconfig,
0136                     &port_config[0], wcd->active_ports,
0137                     wcd->sruntime);
0138 }
0139 EXPORT_SYMBOL_GPL(wcd938x_sdw_hw_params);
0140 
0141 int wcd938x_sdw_free(struct wcd938x_sdw_priv *wcd,
0142              struct snd_pcm_substream *substream,
0143              struct snd_soc_dai *dai)
0144 {
0145     sdw_stream_remove_slave(wcd->sdev, wcd->sruntime);
0146 
0147     return 0;
0148 }
0149 EXPORT_SYMBOL_GPL(wcd938x_sdw_free);
0150 
0151 int wcd938x_sdw_set_sdw_stream(struct wcd938x_sdw_priv *wcd,
0152                    struct snd_soc_dai *dai,
0153                    void *stream, int direction)
0154 {
0155     wcd->sruntime = stream;
0156 
0157     return 0;
0158 }
0159 EXPORT_SYMBOL_GPL(wcd938x_sdw_set_sdw_stream);
0160 
0161 static int wcd9380_update_status(struct sdw_slave *slave,
0162                  enum sdw_slave_status status)
0163 {
0164     return 0;
0165 }
0166 
0167 static int wcd9380_bus_config(struct sdw_slave *slave,
0168                   struct sdw_bus_params *params)
0169 {
0170     sdw_write(slave, SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(params->next_bank),  0x01);
0171 
0172     return 0;
0173 }
0174 
0175 static int wcd9380_interrupt_callback(struct sdw_slave *slave,
0176                       struct sdw_slave_intr_status *status)
0177 {
0178     struct wcd938x_sdw_priv *wcd = dev_get_drvdata(&slave->dev);
0179     struct irq_domain *slave_irq = wcd->slave_irq;
0180     struct regmap *regmap = dev_get_regmap(&slave->dev, NULL);
0181     u32 sts1, sts2, sts3;
0182 
0183     do {
0184         handle_nested_irq(irq_find_mapping(slave_irq, 0));
0185         regmap_read(regmap, WCD938X_DIGITAL_INTR_STATUS_0, &sts1);
0186         regmap_read(regmap, WCD938X_DIGITAL_INTR_STATUS_1, &sts2);
0187         regmap_read(regmap, WCD938X_DIGITAL_INTR_STATUS_2, &sts3);
0188 
0189     } while (sts1 || sts2 || sts3);
0190 
0191     return IRQ_HANDLED;
0192 }
0193 
0194 static struct sdw_slave_ops wcd9380_slave_ops = {
0195     .update_status = wcd9380_update_status,
0196     .interrupt_callback = wcd9380_interrupt_callback,
0197     .bus_config = wcd9380_bus_config,
0198 };
0199 
0200 static int wcd938x_sdw_component_bind(struct device *dev,
0201                       struct device *master, void *data)
0202 {
0203     return 0;
0204 }
0205 
0206 static void wcd938x_sdw_component_unbind(struct device *dev,
0207                      struct device *master, void *data)
0208 {
0209 }
0210 
0211 static const struct component_ops wcd938x_sdw_component_ops = {
0212     .bind   = wcd938x_sdw_component_bind,
0213     .unbind = wcd938x_sdw_component_unbind,
0214 };
0215 
0216 static int wcd9380_probe(struct sdw_slave *pdev,
0217              const struct sdw_device_id *id)
0218 {
0219     struct device *dev = &pdev->dev;
0220     struct wcd938x_sdw_priv *wcd;
0221     int ret;
0222 
0223     wcd = devm_kzalloc(dev, sizeof(*wcd), GFP_KERNEL);
0224     if (!wcd)
0225         return -ENOMEM;
0226 
0227     /**
0228      * Port map index starts with 0, however the data port for this codec
0229      * are from index 1
0230      */
0231     if (of_property_read_bool(dev->of_node, "qcom,tx-port-mapping")) {
0232         wcd->is_tx = true;
0233         ret = of_property_read_u32_array(dev->of_node, "qcom,tx-port-mapping",
0234                          &pdev->m_port_map[1],
0235                          WCD938X_MAX_TX_SWR_PORTS);
0236     } else {
0237         ret = of_property_read_u32_array(dev->of_node, "qcom,rx-port-mapping",
0238                          &pdev->m_port_map[1],
0239                          WCD938X_MAX_SWR_PORTS);
0240     }
0241 
0242     if (ret < 0)
0243         dev_info(dev, "Static Port mapping not specified\n");
0244 
0245     wcd->sdev = pdev;
0246     dev_set_drvdata(dev, wcd);
0247 
0248     pdev->prop.scp_int1_mask = SDW_SCP_INT1_IMPL_DEF |
0249                     SDW_SCP_INT1_BUS_CLASH |
0250                     SDW_SCP_INT1_PARITY;
0251     pdev->prop.lane_control_support = true;
0252     pdev->prop.simple_clk_stop_capable = true;
0253     if (wcd->is_tx) {
0254         pdev->prop.source_ports = GENMASK(WCD938X_MAX_SWR_PORTS, 0);
0255         pdev->prop.src_dpn_prop = wcd938x_dpn_prop;
0256         wcd->ch_info = &wcd938x_sdw_tx_ch_info[0];
0257         pdev->prop.wake_capable = true;
0258     } else {
0259         pdev->prop.sink_ports = GENMASK(WCD938X_MAX_SWR_PORTS, 0);
0260         pdev->prop.sink_dpn_prop = wcd938x_dpn_prop;
0261         wcd->ch_info = &wcd938x_sdw_rx_ch_info[0];
0262     }
0263 
0264     pm_runtime_set_autosuspend_delay(dev, 3000);
0265     pm_runtime_use_autosuspend(dev);
0266     pm_runtime_mark_last_busy(dev);
0267     pm_runtime_set_active(dev);
0268     pm_runtime_enable(dev);
0269 
0270     return component_add(dev, &wcd938x_sdw_component_ops);
0271 }
0272 
0273 static const struct sdw_device_id wcd9380_slave_id[] = {
0274     SDW_SLAVE_ENTRY(0x0217, 0x10d, 0),
0275     {},
0276 };
0277 MODULE_DEVICE_TABLE(sdw, wcd9380_slave_id);
0278 
0279 static int __maybe_unused wcd938x_sdw_runtime_suspend(struct device *dev)
0280 {
0281     struct regmap *regmap = dev_get_regmap(dev, NULL);
0282 
0283     if (regmap) {
0284         regcache_cache_only(regmap, true);
0285         regcache_mark_dirty(regmap);
0286     }
0287     return 0;
0288 }
0289 
0290 static int __maybe_unused wcd938x_sdw_runtime_resume(struct device *dev)
0291 {
0292     struct regmap *regmap = dev_get_regmap(dev, NULL);
0293 
0294     if (regmap) {
0295         regcache_cache_only(regmap, false);
0296         regcache_sync(regmap);
0297     }
0298 
0299     pm_runtime_mark_last_busy(dev);
0300 
0301     return 0;
0302 }
0303 
0304 static const struct dev_pm_ops wcd938x_sdw_pm_ops = {
0305     SET_RUNTIME_PM_OPS(wcd938x_sdw_runtime_suspend, wcd938x_sdw_runtime_resume, NULL)
0306 };
0307 
0308 
0309 static struct sdw_driver wcd9380_codec_driver = {
0310     .probe  = wcd9380_probe,
0311     .ops = &wcd9380_slave_ops,
0312     .id_table = wcd9380_slave_id,
0313     .driver = {
0314         .name   = "wcd9380-codec",
0315         .pm = &wcd938x_sdw_pm_ops,
0316     }
0317 };
0318 module_sdw_driver(wcd9380_codec_driver);
0319 
0320 MODULE_DESCRIPTION("WCD938X SDW codec driver");
0321 MODULE_LICENSE("GPL");