linux/sound/soc/codecs/wcd938x-sdw.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (c) 2021, Linaro Limited
   3
   4#include <linux/module.h>
   5#include <linux/slab.h>
   6#include <linux/platform_device.h>
   7#include <linux/device.h>
   8#include <linux/kernel.h>
   9#include <linux/component.h>
  10#include <linux/pm_runtime.h>
  11#include <linux/irq.h>
  12#include <linux/irqdomain.h>
  13#include <linux/of.h>
  14#include <linux/soundwire/sdw.h>
  15#include <linux/soundwire/sdw_type.h>
  16#include <linux/soundwire/sdw_registers.h>
  17#include <linux/regmap.h>
  18#include <sound/soc.h>
  19#include <sound/soc-dapm.h>
  20#include "wcd938x.h"
  21
  22#define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m) (0xE0 + 0x10 * (m))
  23
  24static struct wcd938x_sdw_ch_info wcd938x_sdw_rx_ch_info[] = {
  25        WCD_SDW_CH(WCD938X_HPH_L, WCD938X_HPH_PORT, BIT(0)),
  26        WCD_SDW_CH(WCD938X_HPH_R, WCD938X_HPH_PORT, BIT(1)),
  27        WCD_SDW_CH(WCD938X_CLSH, WCD938X_CLSH_PORT, BIT(0)),
  28        WCD_SDW_CH(WCD938X_COMP_L, WCD938X_COMP_PORT, BIT(0)),
  29        WCD_SDW_CH(WCD938X_COMP_R, WCD938X_COMP_PORT, BIT(1)),
  30        WCD_SDW_CH(WCD938X_LO, WCD938X_LO_PORT, BIT(0)),
  31        WCD_SDW_CH(WCD938X_DSD_L, WCD938X_DSD_PORT, BIT(0)),
  32        WCD_SDW_CH(WCD938X_DSD_R, WCD938X_DSD_PORT, BIT(1)),
  33};
  34
  35static struct wcd938x_sdw_ch_info wcd938x_sdw_tx_ch_info[] = {
  36        WCD_SDW_CH(WCD938X_ADC1, WCD938X_ADC_1_2_PORT, BIT(0)),
  37        WCD_SDW_CH(WCD938X_ADC2, WCD938X_ADC_1_2_PORT, BIT(1)),
  38        WCD_SDW_CH(WCD938X_ADC3, WCD938X_ADC_3_4_PORT, BIT(0)),
  39        WCD_SDW_CH(WCD938X_ADC4, WCD938X_ADC_3_4_PORT, BIT(1)),
  40        WCD_SDW_CH(WCD938X_DMIC0, WCD938X_DMIC_0_3_MBHC_PORT, BIT(0)),
  41        WCD_SDW_CH(WCD938X_DMIC1, WCD938X_DMIC_0_3_MBHC_PORT, BIT(1)),
  42        WCD_SDW_CH(WCD938X_MBHC, WCD938X_DMIC_0_3_MBHC_PORT, BIT(2)),
  43        WCD_SDW_CH(WCD938X_DMIC2, WCD938X_DMIC_0_3_MBHC_PORT, BIT(2)),
  44        WCD_SDW_CH(WCD938X_DMIC3, WCD938X_DMIC_0_3_MBHC_PORT, BIT(3)),
  45        WCD_SDW_CH(WCD938X_DMIC4, WCD938X_DMIC_4_7_PORT, BIT(0)),
  46        WCD_SDW_CH(WCD938X_DMIC5, WCD938X_DMIC_4_7_PORT, BIT(1)),
  47        WCD_SDW_CH(WCD938X_DMIC6, WCD938X_DMIC_4_7_PORT, BIT(2)),
  48        WCD_SDW_CH(WCD938X_DMIC7, WCD938X_DMIC_4_7_PORT, BIT(3)),
  49};
  50
  51static struct sdw_dpn_prop wcd938x_dpn_prop[WCD938X_MAX_SWR_PORTS] = {
  52        {
  53                .num = 1,
  54                .type = SDW_DPN_SIMPLE,
  55                .min_ch = 1,
  56                .max_ch = 8,
  57                .simple_ch_prep_sm = true,
  58        }, {
  59                .num = 2,
  60                .type = SDW_DPN_SIMPLE,
  61                .min_ch = 1,
  62                .max_ch = 4,
  63                .simple_ch_prep_sm = true,
  64        }, {
  65                .num = 3,
  66                .type = SDW_DPN_SIMPLE,
  67                .min_ch = 1,
  68                .max_ch = 4,
  69                .simple_ch_prep_sm = true,
  70        }, {
  71                .num = 4,
  72                .type = SDW_DPN_SIMPLE,
  73                .min_ch = 1,
  74                .max_ch = 4,
  75                .simple_ch_prep_sm = true,
  76        }, {
  77                .num = 5,
  78                .type = SDW_DPN_SIMPLE,
  79                .min_ch = 1,
  80                .max_ch = 4,
  81                .simple_ch_prep_sm = true,
  82        }
  83};
  84
  85struct device *wcd938x_sdw_device_get(struct device_node *np)
  86{
  87        return bus_find_device_by_of_node(&sdw_bus_type, np);
  88
  89}
  90EXPORT_SYMBOL_GPL(wcd938x_sdw_device_get);
  91
  92int wcd938x_swr_get_current_bank(struct sdw_slave *sdev)
  93{
  94        int bank;
  95
  96        bank  = sdw_read(sdev, SDW_SCP_CTRL);
  97
  98        return ((bank & 0x40) ? 1 : 0);
  99}
 100EXPORT_SYMBOL_GPL(wcd938x_swr_get_current_bank);
 101
 102int wcd938x_sdw_hw_params(struct wcd938x_sdw_priv *wcd,
 103                          struct snd_pcm_substream *substream,
 104                          struct snd_pcm_hw_params *params,
 105                          struct snd_soc_dai *dai)
 106{
 107        struct sdw_port_config port_config[WCD938X_MAX_SWR_PORTS];
 108        unsigned long ch_mask;
 109        int i, j;
 110
 111        wcd->sconfig.ch_count = 1;
 112        wcd->active_ports = 0;
 113        for (i = 0; i < WCD938X_MAX_SWR_PORTS; i++) {
 114                ch_mask = wcd->port_config[i].ch_mask;
 115
 116                if (!ch_mask)
 117                        continue;
 118
 119                for_each_set_bit(j, &ch_mask, 4)
 120                        wcd->sconfig.ch_count++;
 121
 122                port_config[wcd->active_ports] = wcd->port_config[i];
 123                wcd->active_ports++;
 124        }
 125
 126        wcd->sconfig.bps = 1;
 127        wcd->sconfig.frame_rate =  params_rate(params);
 128        if (wcd->is_tx)
 129                wcd->sconfig.direction = SDW_DATA_DIR_TX;
 130        else
 131                wcd->sconfig.direction = SDW_DATA_DIR_RX;
 132
 133        wcd->sconfig.type = SDW_STREAM_PCM;
 134
 135        return sdw_stream_add_slave(wcd->sdev, &wcd->sconfig,
 136                                    &port_config[0], wcd->active_ports,
 137                                    wcd->sruntime);
 138}
 139EXPORT_SYMBOL_GPL(wcd938x_sdw_hw_params);
 140
 141int wcd938x_sdw_free(struct wcd938x_sdw_priv *wcd,
 142                     struct snd_pcm_substream *substream,
 143                     struct snd_soc_dai *dai)
 144{
 145        sdw_stream_remove_slave(wcd->sdev, wcd->sruntime);
 146
 147        return 0;
 148}
 149EXPORT_SYMBOL_GPL(wcd938x_sdw_free);
 150
 151int wcd938x_sdw_set_sdw_stream(struct wcd938x_sdw_priv *wcd,
 152                               struct snd_soc_dai *dai,
 153                               void *stream, int direction)
 154{
 155        wcd->sruntime = stream;
 156
 157        return 0;
 158}
 159EXPORT_SYMBOL_GPL(wcd938x_sdw_set_sdw_stream);
 160
 161static int wcd9380_update_status(struct sdw_slave *slave,
 162                                 enum sdw_slave_status status)
 163{
 164        return 0;
 165}
 166
 167static int wcd9380_bus_config(struct sdw_slave *slave,
 168                              struct sdw_bus_params *params)
 169{
 170        sdw_write(slave, SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(params->next_bank),  0x01);
 171
 172        return 0;
 173}
 174
 175static int wcd9380_interrupt_callback(struct sdw_slave *slave,
 176                                      struct sdw_slave_intr_status *status)
 177{
 178        struct wcd938x_sdw_priv *wcd = dev_get_drvdata(&slave->dev);
 179        struct irq_domain *slave_irq = wcd->slave_irq;
 180        struct regmap *regmap = dev_get_regmap(&slave->dev, NULL);
 181        u32 sts1, sts2, sts3;
 182
 183        do {
 184                handle_nested_irq(irq_find_mapping(slave_irq, 0));
 185                regmap_read(regmap, WCD938X_DIGITAL_INTR_STATUS_0, &sts1);
 186                regmap_read(regmap, WCD938X_DIGITAL_INTR_STATUS_1, &sts2);
 187                regmap_read(regmap, WCD938X_DIGITAL_INTR_STATUS_2, &sts3);
 188
 189        } while (sts1 || sts2 || sts3);
 190
 191        return IRQ_HANDLED;
 192}
 193
 194static struct sdw_slave_ops wcd9380_slave_ops = {
 195        .update_status = wcd9380_update_status,
 196        .interrupt_callback = wcd9380_interrupt_callback,
 197        .bus_config = wcd9380_bus_config,
 198};
 199
 200static int wcd938x_sdw_component_bind(struct device *dev,
 201                                      struct device *master, void *data)
 202{
 203        return 0;
 204}
 205
 206static void wcd938x_sdw_component_unbind(struct device *dev,
 207                                         struct device *master, void *data)
 208{
 209}
 210
 211static const struct component_ops wcd938x_sdw_component_ops = {
 212        .bind   = wcd938x_sdw_component_bind,
 213        .unbind = wcd938x_sdw_component_unbind,
 214};
 215
 216static int wcd9380_probe(struct sdw_slave *pdev,
 217                         const struct sdw_device_id *id)
 218{
 219        struct device *dev = &pdev->dev;
 220        struct wcd938x_sdw_priv *wcd;
 221        int ret;
 222
 223        wcd = devm_kzalloc(dev, sizeof(*wcd), GFP_KERNEL);
 224        if (!wcd)
 225                return -ENOMEM;
 226
 227        /**
 228         * Port map index starts with 0, however the data port for this codec
 229         * are from index 1
 230         */
 231        if (of_property_read_bool(dev->of_node, "qcom,tx-port-mapping")) {
 232                wcd->is_tx = true;
 233                ret = of_property_read_u32_array(dev->of_node, "qcom,tx-port-mapping",
 234                                                 &pdev->m_port_map[1],
 235                                                 WCD938X_MAX_TX_SWR_PORTS);
 236        } else {
 237                ret = of_property_read_u32_array(dev->of_node, "qcom,rx-port-mapping",
 238                                                 &pdev->m_port_map[1],
 239                                                 WCD938X_MAX_SWR_PORTS);
 240        }
 241
 242        if (ret < 0)
 243                dev_info(dev, "Static Port mapping not specified\n");
 244
 245        wcd->sdev = pdev;
 246        dev_set_drvdata(dev, wcd);
 247
 248        pdev->prop.scp_int1_mask = SDW_SCP_INT1_IMPL_DEF |
 249                                        SDW_SCP_INT1_BUS_CLASH |
 250                                        SDW_SCP_INT1_PARITY;
 251        pdev->prop.lane_control_support = true;
 252        if (wcd->is_tx) {
 253                pdev->prop.source_ports = GENMASK(WCD938X_MAX_SWR_PORTS, 0);
 254                pdev->prop.src_dpn_prop = wcd938x_dpn_prop;
 255                wcd->ch_info = &wcd938x_sdw_tx_ch_info[0];
 256                pdev->prop.wake_capable = true;
 257        } else {
 258                pdev->prop.sink_ports = GENMASK(WCD938X_MAX_SWR_PORTS, 0);
 259                pdev->prop.sink_dpn_prop = wcd938x_dpn_prop;
 260                wcd->ch_info = &wcd938x_sdw_rx_ch_info[0];
 261        }
 262
 263        pm_runtime_set_autosuspend_delay(dev, 3000);
 264        pm_runtime_use_autosuspend(dev);
 265        pm_runtime_mark_last_busy(dev);
 266        pm_runtime_set_active(dev);
 267        pm_runtime_enable(dev);
 268
 269        return component_add(dev, &wcd938x_sdw_component_ops);
 270}
 271
 272static const struct sdw_device_id wcd9380_slave_id[] = {
 273        SDW_SLAVE_ENTRY(0x0217, 0x10d, 0),
 274        {},
 275};
 276MODULE_DEVICE_TABLE(sdw, wcd9380_slave_id);
 277
 278static int __maybe_unused wcd938x_sdw_runtime_suspend(struct device *dev)
 279{
 280        struct regmap *regmap = dev_get_regmap(dev, NULL);
 281
 282        if (regmap) {
 283                regcache_cache_only(regmap, true);
 284                regcache_mark_dirty(regmap);
 285        }
 286        return 0;
 287}
 288
 289static int __maybe_unused wcd938x_sdw_runtime_resume(struct device *dev)
 290{
 291        struct regmap *regmap = dev_get_regmap(dev, NULL);
 292
 293        if (regmap) {
 294                regcache_cache_only(regmap, false);
 295                regcache_sync(regmap);
 296        }
 297
 298        pm_runtime_mark_last_busy(dev);
 299
 300        return 0;
 301}
 302
 303static const struct dev_pm_ops wcd938x_sdw_pm_ops = {
 304        SET_RUNTIME_PM_OPS(wcd938x_sdw_runtime_suspend, wcd938x_sdw_runtime_resume, NULL)
 305};
 306
 307
 308static struct sdw_driver wcd9380_codec_driver = {
 309        .probe  = wcd9380_probe,
 310        .ops = &wcd9380_slave_ops,
 311        .id_table = wcd9380_slave_id,
 312        .driver = {
 313                .name   = "wcd9380-codec",
 314                .pm = &wcd938x_sdw_pm_ops,
 315        }
 316};
 317module_sdw_driver(wcd9380_codec_driver);
 318
 319MODULE_DESCRIPTION("WCD938X SDW codec driver");
 320MODULE_LICENSE("GPL");
 321