1*03f6fc6dSOder Chiou // SPDX-License-Identifier: GPL-2.0-only 2*03f6fc6dSOder Chiou // 3*03f6fc6dSOder Chiou // rt5682-sdw.c -- RT5682 ALSA SoC audio component driver 4*03f6fc6dSOder Chiou // 5*03f6fc6dSOder Chiou // Copyright 2019 Realtek Semiconductor Corp. 6*03f6fc6dSOder Chiou // Author: Oder Chiou <oder_chiou@realtek.com> 7*03f6fc6dSOder Chiou // 8*03f6fc6dSOder Chiou 9*03f6fc6dSOder Chiou #include <linux/module.h> 10*03f6fc6dSOder Chiou #include <linux/moduleparam.h> 11*03f6fc6dSOder Chiou #include <linux/init.h> 12*03f6fc6dSOder Chiou #include <linux/delay.h> 13*03f6fc6dSOder Chiou #include <linux/pm.h> 14*03f6fc6dSOder Chiou #include <linux/acpi.h> 15*03f6fc6dSOder Chiou #include <linux/gpio.h> 16*03f6fc6dSOder Chiou #include <linux/of_gpio.h> 17*03f6fc6dSOder Chiou #include <linux/regulator/consumer.h> 18*03f6fc6dSOder Chiou #include <linux/mutex.h> 19*03f6fc6dSOder Chiou #include <linux/soundwire/sdw.h> 20*03f6fc6dSOder Chiou #include <linux/soundwire/sdw_type.h> 21*03f6fc6dSOder Chiou #include <sound/core.h> 22*03f6fc6dSOder Chiou #include <sound/pcm.h> 23*03f6fc6dSOder Chiou #include <sound/pcm_params.h> 24*03f6fc6dSOder Chiou #include <sound/jack.h> 25*03f6fc6dSOder Chiou #include <sound/soc.h> 26*03f6fc6dSOder Chiou #include <sound/soc-dapm.h> 27*03f6fc6dSOder Chiou #include <sound/initval.h> 28*03f6fc6dSOder Chiou #include <sound/tlv.h> 29*03f6fc6dSOder Chiou 30*03f6fc6dSOder Chiou #include "rt5682.h" 31*03f6fc6dSOder Chiou #include "rt5682-sdw.h" 32*03f6fc6dSOder Chiou 33*03f6fc6dSOder Chiou static bool rt5682_sdw_readable_register(struct device *dev, unsigned int reg) 34*03f6fc6dSOder Chiou { 35*03f6fc6dSOder Chiou switch (reg) { 36*03f6fc6dSOder Chiou case 0x00e0: 37*03f6fc6dSOder Chiou case 0x00f0: 38*03f6fc6dSOder Chiou case 0x3000: 39*03f6fc6dSOder Chiou case 0x3001: 40*03f6fc6dSOder Chiou case 0x3004: 41*03f6fc6dSOder Chiou case 0x3005: 42*03f6fc6dSOder Chiou case 0x3008: 43*03f6fc6dSOder Chiou return true; 44*03f6fc6dSOder Chiou default: 45*03f6fc6dSOder Chiou return false; 46*03f6fc6dSOder Chiou } 47*03f6fc6dSOder Chiou } 48*03f6fc6dSOder Chiou 49*03f6fc6dSOder Chiou const struct regmap_config rt5682_sdw_regmap = { 50*03f6fc6dSOder Chiou .name = "sdw", 51*03f6fc6dSOder Chiou .reg_bits = 32, 52*03f6fc6dSOder Chiou .val_bits = 8, 53*03f6fc6dSOder Chiou .max_register = RT5682_I2C_MODE, 54*03f6fc6dSOder Chiou .readable_reg = rt5682_sdw_readable_register, 55*03f6fc6dSOder Chiou .cache_type = REGCACHE_NONE, 56*03f6fc6dSOder Chiou .use_single_read = true, 57*03f6fc6dSOder Chiou .use_single_write = true, 58*03f6fc6dSOder Chiou }; 59*03f6fc6dSOder Chiou 60*03f6fc6dSOder Chiou static int rt5682_update_status(struct sdw_slave *slave, 61*03f6fc6dSOder Chiou enum sdw_slave_status status) 62*03f6fc6dSOder Chiou { 63*03f6fc6dSOder Chiou struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev); 64*03f6fc6dSOder Chiou 65*03f6fc6dSOder Chiou /* Update the status */ 66*03f6fc6dSOder Chiou rt5682->status = status; 67*03f6fc6dSOder Chiou 68*03f6fc6dSOder Chiou if (status == SDW_SLAVE_UNATTACHED) 69*03f6fc6dSOder Chiou rt5682->hw_init = false; 70*03f6fc6dSOder Chiou 71*03f6fc6dSOder Chiou /* 72*03f6fc6dSOder Chiou * Perform initialization only if slave status is present and 73*03f6fc6dSOder Chiou * hw_init flag is false 74*03f6fc6dSOder Chiou */ 75*03f6fc6dSOder Chiou if (rt5682->hw_init || rt5682->status != SDW_SLAVE_ATTACHED) 76*03f6fc6dSOder Chiou return 0; 77*03f6fc6dSOder Chiou 78*03f6fc6dSOder Chiou /* perform I/O transfers required for Slave initialization */ 79*03f6fc6dSOder Chiou return rt5682_io_init(&slave->dev, slave); 80*03f6fc6dSOder Chiou } 81*03f6fc6dSOder Chiou 82*03f6fc6dSOder Chiou static int rt5682_read_prop(struct sdw_slave *slave) 83*03f6fc6dSOder Chiou { 84*03f6fc6dSOder Chiou struct sdw_slave_prop *prop = &slave->prop; 85*03f6fc6dSOder Chiou int nval, i, num_of_ports = 1; 86*03f6fc6dSOder Chiou u32 bit; 87*03f6fc6dSOder Chiou unsigned long addr; 88*03f6fc6dSOder Chiou struct sdw_dpn_prop *dpn; 89*03f6fc6dSOder Chiou 90*03f6fc6dSOder Chiou prop->paging_support = false; 91*03f6fc6dSOder Chiou 92*03f6fc6dSOder Chiou /* first we need to allocate memory for set bits in port lists */ 93*03f6fc6dSOder Chiou prop->source_ports = 0x4; /* BITMAP: 00000100 */ 94*03f6fc6dSOder Chiou prop->sink_ports = 0x2; /* BITMAP: 00000010 */ 95*03f6fc6dSOder Chiou 96*03f6fc6dSOder Chiou nval = hweight32(prop->source_ports); 97*03f6fc6dSOder Chiou num_of_ports += nval; 98*03f6fc6dSOder Chiou prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, 99*03f6fc6dSOder Chiou sizeof(*prop->src_dpn_prop), 100*03f6fc6dSOder Chiou GFP_KERNEL); 101*03f6fc6dSOder Chiou if (!prop->src_dpn_prop) 102*03f6fc6dSOder Chiou return -ENOMEM; 103*03f6fc6dSOder Chiou 104*03f6fc6dSOder Chiou i = 0; 105*03f6fc6dSOder Chiou dpn = prop->src_dpn_prop; 106*03f6fc6dSOder Chiou addr = prop->source_ports; 107*03f6fc6dSOder Chiou for_each_set_bit(bit, &addr, 32) { 108*03f6fc6dSOder Chiou dpn[i].num = bit; 109*03f6fc6dSOder Chiou dpn[i].type = SDW_DPN_FULL; 110*03f6fc6dSOder Chiou dpn[i].simple_ch_prep_sm = true; 111*03f6fc6dSOder Chiou dpn[i].ch_prep_timeout = 10; 112*03f6fc6dSOder Chiou i++; 113*03f6fc6dSOder Chiou } 114*03f6fc6dSOder Chiou 115*03f6fc6dSOder Chiou /* do this again for sink now */ 116*03f6fc6dSOder Chiou nval = hweight32(prop->sink_ports); 117*03f6fc6dSOder Chiou num_of_ports += nval; 118*03f6fc6dSOder Chiou prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, 119*03f6fc6dSOder Chiou sizeof(*prop->sink_dpn_prop), 120*03f6fc6dSOder Chiou GFP_KERNEL); 121*03f6fc6dSOder Chiou if (!prop->sink_dpn_prop) 122*03f6fc6dSOder Chiou return -ENOMEM; 123*03f6fc6dSOder Chiou 124*03f6fc6dSOder Chiou i = 0; 125*03f6fc6dSOder Chiou dpn = prop->sink_dpn_prop; 126*03f6fc6dSOder Chiou addr = prop->sink_ports; 127*03f6fc6dSOder Chiou for_each_set_bit(bit, &addr, 32) { 128*03f6fc6dSOder Chiou dpn[i].num = bit; 129*03f6fc6dSOder Chiou dpn[i].type = SDW_DPN_FULL; 130*03f6fc6dSOder Chiou dpn[i].simple_ch_prep_sm = true; 131*03f6fc6dSOder Chiou dpn[i].ch_prep_timeout = 10; 132*03f6fc6dSOder Chiou i++; 133*03f6fc6dSOder Chiou } 134*03f6fc6dSOder Chiou 135*03f6fc6dSOder Chiou /* Allocate port_ready based on num_of_ports */ 136*03f6fc6dSOder Chiou slave->port_ready = devm_kcalloc(&slave->dev, num_of_ports, 137*03f6fc6dSOder Chiou sizeof(*slave->port_ready), 138*03f6fc6dSOder Chiou GFP_KERNEL); 139*03f6fc6dSOder Chiou if (!slave->port_ready) 140*03f6fc6dSOder Chiou return -ENOMEM; 141*03f6fc6dSOder Chiou 142*03f6fc6dSOder Chiou /* Initialize completion */ 143*03f6fc6dSOder Chiou for (i = 0; i < num_of_ports; i++) 144*03f6fc6dSOder Chiou init_completion(&slave->port_ready[i]); 145*03f6fc6dSOder Chiou 146*03f6fc6dSOder Chiou /* set the timeout values */ 147*03f6fc6dSOder Chiou prop->clk_stop_timeout = 20; 148*03f6fc6dSOder Chiou 149*03f6fc6dSOder Chiou /* wake-up event */ 150*03f6fc6dSOder Chiou prop->wake_capable = 1; 151*03f6fc6dSOder Chiou 152*03f6fc6dSOder Chiou return 0; 153*03f6fc6dSOder Chiou } 154*03f6fc6dSOder Chiou 155*03f6fc6dSOder Chiou /* Bus clock frequency */ 156*03f6fc6dSOder Chiou #define RT5682_CLK_FREQ_9600000HZ 9600000 157*03f6fc6dSOder Chiou #define RT5682_CLK_FREQ_12000000HZ 12000000 158*03f6fc6dSOder Chiou #define RT5682_CLK_FREQ_6000000HZ 6000000 159*03f6fc6dSOder Chiou #define RT5682_CLK_FREQ_4800000HZ 4800000 160*03f6fc6dSOder Chiou #define RT5682_CLK_FREQ_2400000HZ 2400000 161*03f6fc6dSOder Chiou #define RT5682_CLK_FREQ_12288000HZ 12288000 162*03f6fc6dSOder Chiou 163*03f6fc6dSOder Chiou int rt5682_clock_config(struct device *dev) 164*03f6fc6dSOder Chiou { 165*03f6fc6dSOder Chiou struct rt5682_priv *rt5682 = dev_get_drvdata(dev); 166*03f6fc6dSOder Chiou unsigned int clk_freq, value; 167*03f6fc6dSOder Chiou 168*03f6fc6dSOder Chiou clk_freq = (rt5682->params.curr_dr_freq >> 1); 169*03f6fc6dSOder Chiou 170*03f6fc6dSOder Chiou switch (clk_freq) { 171*03f6fc6dSOder Chiou case RT5682_CLK_FREQ_12000000HZ: 172*03f6fc6dSOder Chiou value = 0x0; 173*03f6fc6dSOder Chiou break; 174*03f6fc6dSOder Chiou case RT5682_CLK_FREQ_6000000HZ: 175*03f6fc6dSOder Chiou value = 0x1; 176*03f6fc6dSOder Chiou break; 177*03f6fc6dSOder Chiou case RT5682_CLK_FREQ_9600000HZ: 178*03f6fc6dSOder Chiou value = 0x2; 179*03f6fc6dSOder Chiou break; 180*03f6fc6dSOder Chiou case RT5682_CLK_FREQ_4800000HZ: 181*03f6fc6dSOder Chiou value = 0x3; 182*03f6fc6dSOder Chiou break; 183*03f6fc6dSOder Chiou case RT5682_CLK_FREQ_2400000HZ: 184*03f6fc6dSOder Chiou value = 0x4; 185*03f6fc6dSOder Chiou break; 186*03f6fc6dSOder Chiou case RT5682_CLK_FREQ_12288000HZ: 187*03f6fc6dSOder Chiou value = 0x5; 188*03f6fc6dSOder Chiou break; 189*03f6fc6dSOder Chiou default: 190*03f6fc6dSOder Chiou return -EINVAL; 191*03f6fc6dSOder Chiou } 192*03f6fc6dSOder Chiou 193*03f6fc6dSOder Chiou regmap_write(rt5682->sdw_regmap, 0xe0, value); 194*03f6fc6dSOder Chiou regmap_write(rt5682->sdw_regmap, 0xf0, value); 195*03f6fc6dSOder Chiou 196*03f6fc6dSOder Chiou dev_dbg(dev, "%s complete, clk_freq=%d\n", __func__, clk_freq); 197*03f6fc6dSOder Chiou 198*03f6fc6dSOder Chiou return 0; 199*03f6fc6dSOder Chiou } 200*03f6fc6dSOder Chiou 201*03f6fc6dSOder Chiou static int rt5682_bus_config(struct sdw_slave *slave, 202*03f6fc6dSOder Chiou struct sdw_bus_params *params) 203*03f6fc6dSOder Chiou { 204*03f6fc6dSOder Chiou struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev); 205*03f6fc6dSOder Chiou int ret; 206*03f6fc6dSOder Chiou 207*03f6fc6dSOder Chiou memcpy(&rt5682->params, params, sizeof(*params)); 208*03f6fc6dSOder Chiou 209*03f6fc6dSOder Chiou ret = rt5682_clock_config(&slave->dev); 210*03f6fc6dSOder Chiou if (ret < 0) 211*03f6fc6dSOder Chiou dev_err(&slave->dev, "Invalid clk config"); 212*03f6fc6dSOder Chiou 213*03f6fc6dSOder Chiou return ret; 214*03f6fc6dSOder Chiou } 215*03f6fc6dSOder Chiou 216*03f6fc6dSOder Chiou static int rt5682_interrupt_callback(struct sdw_slave *slave, 217*03f6fc6dSOder Chiou struct sdw_slave_intr_status *status) 218*03f6fc6dSOder Chiou { 219*03f6fc6dSOder Chiou struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev); 220*03f6fc6dSOder Chiou 221*03f6fc6dSOder Chiou dev_dbg(&slave->dev, 222*03f6fc6dSOder Chiou "%s control_port_stat=%x", __func__, status->control_port); 223*03f6fc6dSOder Chiou 224*03f6fc6dSOder Chiou if (status->control_port & 0x4) { 225*03f6fc6dSOder Chiou mod_delayed_work(system_power_efficient_wq, 226*03f6fc6dSOder Chiou &rt5682->jack_detect_work, msecs_to_jiffies(250)); 227*03f6fc6dSOder Chiou } 228*03f6fc6dSOder Chiou 229*03f6fc6dSOder Chiou return 0; 230*03f6fc6dSOder Chiou } 231*03f6fc6dSOder Chiou 232*03f6fc6dSOder Chiou static struct sdw_slave_ops rt5682_slave_ops = { 233*03f6fc6dSOder Chiou .read_prop = rt5682_read_prop, 234*03f6fc6dSOder Chiou .interrupt_callback = rt5682_interrupt_callback, 235*03f6fc6dSOder Chiou .update_status = rt5682_update_status, 236*03f6fc6dSOder Chiou .bus_config = rt5682_bus_config, 237*03f6fc6dSOder Chiou }; 238*03f6fc6dSOder Chiou 239*03f6fc6dSOder Chiou static int rt5682_sdw_probe(struct sdw_slave *slave, 240*03f6fc6dSOder Chiou const struct sdw_device_id *id) 241*03f6fc6dSOder Chiou { 242*03f6fc6dSOder Chiou struct regmap *regmap; 243*03f6fc6dSOder Chiou 244*03f6fc6dSOder Chiou /* Assign ops */ 245*03f6fc6dSOder Chiou slave->ops = &rt5682_slave_ops; 246*03f6fc6dSOder Chiou 247*03f6fc6dSOder Chiou /* Regmap Initialization */ 248*03f6fc6dSOder Chiou regmap = devm_regmap_init_sdw(slave, &rt5682_sdw_regmap); 249*03f6fc6dSOder Chiou if (IS_ERR(regmap)) 250*03f6fc6dSOder Chiou return -EINVAL; 251*03f6fc6dSOder Chiou 252*03f6fc6dSOder Chiou rt5682_sdw_init(&slave->dev, regmap, slave); 253*03f6fc6dSOder Chiou 254*03f6fc6dSOder Chiou return 0; 255*03f6fc6dSOder Chiou } 256*03f6fc6dSOder Chiou 257*03f6fc6dSOder Chiou static int rt5682_sdw_remove(struct sdw_slave *slave) 258*03f6fc6dSOder Chiou { 259*03f6fc6dSOder Chiou struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev); 260*03f6fc6dSOder Chiou 261*03f6fc6dSOder Chiou if (rt5682 && rt5682->hw_init) 262*03f6fc6dSOder Chiou cancel_delayed_work(&rt5682->jack_detect_work); 263*03f6fc6dSOder Chiou 264*03f6fc6dSOder Chiou return 0; 265*03f6fc6dSOder Chiou } 266*03f6fc6dSOder Chiou 267*03f6fc6dSOder Chiou static const struct sdw_device_id rt5682_id[] = { 268*03f6fc6dSOder Chiou SDW_SLAVE_ENTRY(0x025d, 0x5682, 0), 269*03f6fc6dSOder Chiou {}, 270*03f6fc6dSOder Chiou }; 271*03f6fc6dSOder Chiou MODULE_DEVICE_TABLE(sdw, rt5682_id); 272*03f6fc6dSOder Chiou 273*03f6fc6dSOder Chiou static int rt5682_dev_suspend(struct device *dev) 274*03f6fc6dSOder Chiou { 275*03f6fc6dSOder Chiou struct rt5682_priv *rt5682 = dev_get_drvdata(dev); 276*03f6fc6dSOder Chiou 277*03f6fc6dSOder Chiou if (!rt5682->hw_init) 278*03f6fc6dSOder Chiou return 0; 279*03f6fc6dSOder Chiou 280*03f6fc6dSOder Chiou regcache_cache_only(rt5682->regmap, true); 281*03f6fc6dSOder Chiou regcache_mark_dirty(rt5682->regmap); 282*03f6fc6dSOder Chiou 283*03f6fc6dSOder Chiou return 0; 284*03f6fc6dSOder Chiou } 285*03f6fc6dSOder Chiou 286*03f6fc6dSOder Chiou static int rt5682_dev_resume(struct device *dev) 287*03f6fc6dSOder Chiou { 288*03f6fc6dSOder Chiou struct sdw_slave *slave = dev_to_sdw_dev(dev); 289*03f6fc6dSOder Chiou struct rt5682_priv *rt5682 = dev_get_drvdata(dev); 290*03f6fc6dSOder Chiou unsigned long time; 291*03f6fc6dSOder Chiou 292*03f6fc6dSOder Chiou if (!rt5682->hw_init) 293*03f6fc6dSOder Chiou return 0; 294*03f6fc6dSOder Chiou 295*03f6fc6dSOder Chiou if (!slave->unattach_request) 296*03f6fc6dSOder Chiou goto regmap_sync; 297*03f6fc6dSOder Chiou 298*03f6fc6dSOder Chiou time = wait_for_completion_timeout(&slave->initialization_complete, 299*03f6fc6dSOder Chiou msecs_to_jiffies(RT5682_PROBE_TIMEOUT)); 300*03f6fc6dSOder Chiou if (!time) { 301*03f6fc6dSOder Chiou dev_err(&slave->dev, "Initialization not complete, timed out\n"); 302*03f6fc6dSOder Chiou return -ETIMEDOUT; 303*03f6fc6dSOder Chiou } 304*03f6fc6dSOder Chiou 305*03f6fc6dSOder Chiou regmap_sync: 306*03f6fc6dSOder Chiou slave->unattach_request = 0; 307*03f6fc6dSOder Chiou regcache_cache_only(rt5682->regmap, false); 308*03f6fc6dSOder Chiou regcache_sync(rt5682->regmap); 309*03f6fc6dSOder Chiou 310*03f6fc6dSOder Chiou return 0; 311*03f6fc6dSOder Chiou } 312*03f6fc6dSOder Chiou 313*03f6fc6dSOder Chiou static const struct dev_pm_ops rt5682_pm = { 314*03f6fc6dSOder Chiou SET_SYSTEM_SLEEP_PM_OPS(rt5682_dev_suspend, rt5682_dev_resume) 315*03f6fc6dSOder Chiou SET_RUNTIME_PM_OPS(rt5682_dev_suspend, rt5682_dev_resume, NULL) 316*03f6fc6dSOder Chiou }; 317*03f6fc6dSOder Chiou 318*03f6fc6dSOder Chiou static struct sdw_driver rt5682_sdw_driver = { 319*03f6fc6dSOder Chiou .driver = { 320*03f6fc6dSOder Chiou .name = "rt5682", 321*03f6fc6dSOder Chiou .owner = THIS_MODULE, 322*03f6fc6dSOder Chiou .pm = &rt5682_pm, 323*03f6fc6dSOder Chiou }, 324*03f6fc6dSOder Chiou .probe = rt5682_sdw_probe, 325*03f6fc6dSOder Chiou .remove = rt5682_sdw_remove, 326*03f6fc6dSOder Chiou .ops = &rt5682_slave_ops, 327*03f6fc6dSOder Chiou .id_table = rt5682_id, 328*03f6fc6dSOder Chiou }; 329*03f6fc6dSOder Chiou module_sdw_driver(rt5682_sdw_driver); 330*03f6fc6dSOder Chiou 331*03f6fc6dSOder Chiou MODULE_DESCRIPTION("ASoC RT5682 driver SDW"); 332*03f6fc6dSOder Chiou MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); 333*03f6fc6dSOder Chiou MODULE_LICENSE("GPL v2"); 334