16c39710dSShuming Fan // SPDX-License-Identifier: GPL-2.0-only
26c39710dSShuming Fan //
36c39710dSShuming Fan // rt712-sdca-sdw.c -- rt712 SDCA ALSA SoC audio driver
46c39710dSShuming Fan //
56c39710dSShuming Fan // Copyright(c) 2023 Realtek Semiconductor Corp.
66c39710dSShuming Fan //
76c39710dSShuming Fan //
86c39710dSShuming Fan
96c39710dSShuming Fan #include <linux/delay.h>
106c39710dSShuming Fan #include <linux/device.h>
116c39710dSShuming Fan #include <linux/mod_devicetable.h>
126c39710dSShuming Fan #include <linux/module.h>
136c39710dSShuming Fan #include <linux/pm_runtime.h>
146c39710dSShuming Fan #include <linux/soundwire/sdw_registers.h>
156c39710dSShuming Fan #include "rt712-sdca.h"
166c39710dSShuming Fan #include "rt712-sdca-sdw.h"
176c39710dSShuming Fan
rt712_sdca_readable_register(struct device * dev,unsigned int reg)186c39710dSShuming Fan static bool rt712_sdca_readable_register(struct device *dev, unsigned int reg)
196c39710dSShuming Fan {
206c39710dSShuming Fan switch (reg) {
216c39710dSShuming Fan case 0x201a ... 0x201f:
226c39710dSShuming Fan case 0x2029 ... 0x202a:
236c39710dSShuming Fan case 0x202d ... 0x2034:
246c39710dSShuming Fan case 0x2230 ... 0x2232:
256c39710dSShuming Fan case 0x2f01 ... 0x2f0a:
266c39710dSShuming Fan case 0x2f35 ... 0x2f36:
276c39710dSShuming Fan case 0x2f50:
286c39710dSShuming Fan case 0x2f54:
296c39710dSShuming Fan case 0x2f58 ... 0x2f5d:
306c39710dSShuming Fan case 0x3201:
316c39710dSShuming Fan case 0x320c:
326c39710dSShuming Fan case 0x3301 ... 0x3303:
336c39710dSShuming Fan case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_GE49, RT712_SDCA_CTL_SELECTED_MODE, 0):
346c39710dSShuming Fan case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_GE49, RT712_SDCA_CTL_DETECTED_MODE, 0):
356c39710dSShuming Fan case SDW_SDCA_CTL(FUNC_NUM_HID, RT712_SDCA_ENT_HID01, RT712_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ...
366c39710dSShuming Fan SDW_SDCA_CTL(FUNC_NUM_HID, RT712_SDCA_ENT_HID01, RT712_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0):
376c39710dSShuming Fan case RT712_BUF_ADDR_HID1 ... RT712_BUF_ADDR_HID2:
386c39710dSShuming Fan return true;
396c39710dSShuming Fan default:
406c39710dSShuming Fan return false;
416c39710dSShuming Fan }
426c39710dSShuming Fan }
436c39710dSShuming Fan
rt712_sdca_volatile_register(struct device * dev,unsigned int reg)446c39710dSShuming Fan static bool rt712_sdca_volatile_register(struct device *dev, unsigned int reg)
456c39710dSShuming Fan {
466c39710dSShuming Fan switch (reg) {
476c39710dSShuming Fan case 0x201b:
486c39710dSShuming Fan case 0x201c:
496c39710dSShuming Fan case 0x201d:
506c39710dSShuming Fan case 0x201f:
516c39710dSShuming Fan case 0x202d ... 0x202f:
526c39710dSShuming Fan case 0x2230:
536c39710dSShuming Fan case 0x2f01:
546c39710dSShuming Fan case 0x2f35:
556c39710dSShuming Fan case 0x320c:
566c39710dSShuming Fan case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_GE49, RT712_SDCA_CTL_DETECTED_MODE, 0):
576c39710dSShuming Fan case SDW_SDCA_CTL(FUNC_NUM_HID, RT712_SDCA_ENT_HID01, RT712_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ...
586c39710dSShuming Fan SDW_SDCA_CTL(FUNC_NUM_HID, RT712_SDCA_ENT_HID01, RT712_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0):
596c39710dSShuming Fan case RT712_BUF_ADDR_HID1 ... RT712_BUF_ADDR_HID2:
606c39710dSShuming Fan return true;
616c39710dSShuming Fan default:
626c39710dSShuming Fan return false;
636c39710dSShuming Fan }
646c39710dSShuming Fan }
656c39710dSShuming Fan
rt712_sdca_mbq_readable_register(struct device * dev,unsigned int reg)666c39710dSShuming Fan static bool rt712_sdca_mbq_readable_register(struct device *dev, unsigned int reg)
676c39710dSShuming Fan {
686c39710dSShuming Fan switch (reg) {
696c39710dSShuming Fan case 0x2000000 ... 0x200008e:
706c39710dSShuming Fan case 0x5300000 ... 0x530000e:
716c39710dSShuming Fan case 0x5400000 ... 0x540000e:
726c39710dSShuming Fan case 0x5600000 ... 0x5600008:
736c39710dSShuming Fan case 0x5700000 ... 0x570000d:
746c39710dSShuming Fan case 0x5800000 ... 0x5800021:
756c39710dSShuming Fan case 0x5900000 ... 0x5900028:
766c39710dSShuming Fan case 0x5a00000 ... 0x5a00009:
776c39710dSShuming Fan case 0x5b00000 ... 0x5b00051:
786c39710dSShuming Fan case 0x5c00000 ... 0x5c0009a:
796c39710dSShuming Fan case 0x5d00000 ... 0x5d00009:
806c39710dSShuming Fan case 0x5f00000 ... 0x5f00030:
816c39710dSShuming Fan case 0x6100000 ... 0x6100068:
826c39710dSShuming Fan case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_L):
836c39710dSShuming Fan case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_R):
846c39710dSShuming Fan case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_L):
856c39710dSShuming Fan case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_R):
866c39710dSShuming Fan case SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_L):
876c39710dSShuming Fan case SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_R):
886c39710dSShuming Fan return true;
896c39710dSShuming Fan default:
906c39710dSShuming Fan return false;
916c39710dSShuming Fan }
926c39710dSShuming Fan }
936c39710dSShuming Fan
rt712_sdca_mbq_volatile_register(struct device * dev,unsigned int reg)946c39710dSShuming Fan static bool rt712_sdca_mbq_volatile_register(struct device *dev, unsigned int reg)
956c39710dSShuming Fan {
966c39710dSShuming Fan switch (reg) {
976c39710dSShuming Fan case 0x2000000:
986c39710dSShuming Fan case 0x200001a:
996c39710dSShuming Fan case 0x2000024:
1006c39710dSShuming Fan case 0x2000046:
1016c39710dSShuming Fan case 0x200008a:
1026c39710dSShuming Fan case 0x5800000:
1036c39710dSShuming Fan case 0x5800001:
1046c39710dSShuming Fan case 0x6100008:
1056c39710dSShuming Fan return true;
1066c39710dSShuming Fan default:
1076c39710dSShuming Fan return false;
1086c39710dSShuming Fan }
1096c39710dSShuming Fan }
1106c39710dSShuming Fan
1116c39710dSShuming Fan static const struct regmap_config rt712_sdca_regmap = {
1126c39710dSShuming Fan .reg_bits = 32,
1136c39710dSShuming Fan .val_bits = 8,
1146c39710dSShuming Fan .readable_reg = rt712_sdca_readable_register,
1156c39710dSShuming Fan .volatile_reg = rt712_sdca_volatile_register,
1166c39710dSShuming Fan .max_register = 0x44ffffff,
1176c39710dSShuming Fan .reg_defaults = rt712_sdca_reg_defaults,
1186c39710dSShuming Fan .num_reg_defaults = ARRAY_SIZE(rt712_sdca_reg_defaults),
119f438c799SMark Brown .cache_type = REGCACHE_MAPLE,
1206c39710dSShuming Fan .use_single_read = true,
1216c39710dSShuming Fan .use_single_write = true,
1226c39710dSShuming Fan };
1236c39710dSShuming Fan
1246c39710dSShuming Fan static const struct regmap_config rt712_sdca_mbq_regmap = {
1256c39710dSShuming Fan .name = "sdw-mbq",
1266c39710dSShuming Fan .reg_bits = 32,
1276c39710dSShuming Fan .val_bits = 16,
1286c39710dSShuming Fan .readable_reg = rt712_sdca_mbq_readable_register,
1296c39710dSShuming Fan .volatile_reg = rt712_sdca_mbq_volatile_register,
1306c39710dSShuming Fan .max_register = 0x41000312,
1316c39710dSShuming Fan .reg_defaults = rt712_sdca_mbq_defaults,
1326c39710dSShuming Fan .num_reg_defaults = ARRAY_SIZE(rt712_sdca_mbq_defaults),
133f438c799SMark Brown .cache_type = REGCACHE_MAPLE,
1346c39710dSShuming Fan .use_single_read = true,
1356c39710dSShuming Fan .use_single_write = true,
1366c39710dSShuming Fan };
1376c39710dSShuming Fan
rt712_sdca_update_status(struct sdw_slave * slave,enum sdw_slave_status status)1386c39710dSShuming Fan static int rt712_sdca_update_status(struct sdw_slave *slave,
1396c39710dSShuming Fan enum sdw_slave_status status)
1406c39710dSShuming Fan {
1416c39710dSShuming Fan struct rt712_sdca_priv *rt712 = dev_get_drvdata(&slave->dev);
1426c39710dSShuming Fan
1436c39710dSShuming Fan if (status == SDW_SLAVE_UNATTACHED)
1446c39710dSShuming Fan rt712->hw_init = false;
1456c39710dSShuming Fan
1466c39710dSShuming Fan if (status == SDW_SLAVE_ATTACHED) {
1476c39710dSShuming Fan if (rt712->hs_jack) {
1486c39710dSShuming Fan /*
1496c39710dSShuming Fan * Due to the SCP_SDCA_INTMASK will be cleared by any reset, and then
1506c39710dSShuming Fan * if the device attached again, we will need to set the setting back.
1516c39710dSShuming Fan * It could avoid losing the jack detection interrupt.
1526c39710dSShuming Fan * This also could sync with the cache value as the rt712_sdca_jack_init set.
1536c39710dSShuming Fan */
1546c39710dSShuming Fan sdw_write_no_pm(rt712->slave, SDW_SCP_SDCA_INTMASK1,
1556c39710dSShuming Fan SDW_SCP_SDCA_INTMASK_SDCA_0);
1566c39710dSShuming Fan sdw_write_no_pm(rt712->slave, SDW_SCP_SDCA_INTMASK2,
1576c39710dSShuming Fan SDW_SCP_SDCA_INTMASK_SDCA_8);
1586c39710dSShuming Fan }
1596c39710dSShuming Fan }
1606c39710dSShuming Fan
1616c39710dSShuming Fan /*
1626c39710dSShuming Fan * Perform initialization only if slave status is present and
1636c39710dSShuming Fan * hw_init flag is false
1646c39710dSShuming Fan */
1655cd02f96SKrzysztof Kozlowski if (rt712->hw_init || status != SDW_SLAVE_ATTACHED)
1666c39710dSShuming Fan return 0;
1676c39710dSShuming Fan
1686c39710dSShuming Fan /* perform I/O transfers required for Slave initialization */
1696c39710dSShuming Fan return rt712_sdca_io_init(&slave->dev, slave);
1706c39710dSShuming Fan }
1716c39710dSShuming Fan
rt712_sdca_read_prop(struct sdw_slave * slave)1726c39710dSShuming Fan static int rt712_sdca_read_prop(struct sdw_slave *slave)
1736c39710dSShuming Fan {
1746c39710dSShuming Fan struct sdw_slave_prop *prop = &slave->prop;
1756c39710dSShuming Fan int nval;
1766c39710dSShuming Fan int i, j;
1776c39710dSShuming Fan u32 bit;
1786c39710dSShuming Fan unsigned long addr;
1796c39710dSShuming Fan struct sdw_dpn_prop *dpn;
1806c39710dSShuming Fan
1816c39710dSShuming Fan prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
1826c39710dSShuming Fan prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY;
1836c39710dSShuming Fan
1846c39710dSShuming Fan prop->paging_support = true;
1856c39710dSShuming Fan
1866c39710dSShuming Fan /* first we need to allocate memory for set bits in port lists */
1876c39710dSShuming Fan prop->source_ports = BIT(4); /* BITMAP: 00010000 */
1886c39710dSShuming Fan prop->sink_ports = BIT(3) | BIT(1); /* BITMAP: 00001010 */
1896c39710dSShuming Fan
1906c39710dSShuming Fan nval = hweight32(prop->source_ports);
1916c39710dSShuming Fan prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval,
1926c39710dSShuming Fan sizeof(*prop->src_dpn_prop), GFP_KERNEL);
1936c39710dSShuming Fan if (!prop->src_dpn_prop)
1946c39710dSShuming Fan return -ENOMEM;
1956c39710dSShuming Fan
1966c39710dSShuming Fan i = 0;
1976c39710dSShuming Fan dpn = prop->src_dpn_prop;
1986c39710dSShuming Fan addr = prop->source_ports;
1996c39710dSShuming Fan for_each_set_bit(bit, &addr, 32) {
2006c39710dSShuming Fan dpn[i].num = bit;
2016c39710dSShuming Fan dpn[i].type = SDW_DPN_FULL;
2026c39710dSShuming Fan dpn[i].simple_ch_prep_sm = true;
2036c39710dSShuming Fan dpn[i].ch_prep_timeout = 10;
2046c39710dSShuming Fan i++;
2056c39710dSShuming Fan }
2066c39710dSShuming Fan
2076c39710dSShuming Fan /* do this again for sink now */
2086c39710dSShuming Fan nval = hweight32(prop->sink_ports);
2096c39710dSShuming Fan prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval,
2106c39710dSShuming Fan sizeof(*prop->sink_dpn_prop), GFP_KERNEL);
2116c39710dSShuming Fan if (!prop->sink_dpn_prop)
2126c39710dSShuming Fan return -ENOMEM;
2136c39710dSShuming Fan
2146c39710dSShuming Fan j = 0;
2156c39710dSShuming Fan dpn = prop->sink_dpn_prop;
2166c39710dSShuming Fan addr = prop->sink_ports;
2176c39710dSShuming Fan for_each_set_bit(bit, &addr, 32) {
2186c39710dSShuming Fan dpn[j].num = bit;
2196c39710dSShuming Fan dpn[j].type = SDW_DPN_FULL;
2206c39710dSShuming Fan dpn[j].simple_ch_prep_sm = true;
2216c39710dSShuming Fan dpn[j].ch_prep_timeout = 10;
2226c39710dSShuming Fan j++;
2236c39710dSShuming Fan }
2246c39710dSShuming Fan
2256c39710dSShuming Fan /* set the timeout values */
2266c39710dSShuming Fan prop->clk_stop_timeout = 1380;
2276c39710dSShuming Fan
2286c39710dSShuming Fan /* wake-up event */
2296c39710dSShuming Fan prop->wake_capable = 1;
2306c39710dSShuming Fan
2316c39710dSShuming Fan return 0;
2326c39710dSShuming Fan }
2336c39710dSShuming Fan
rt712_sdca_interrupt_callback(struct sdw_slave * slave,struct sdw_slave_intr_status * status)2346c39710dSShuming Fan static int rt712_sdca_interrupt_callback(struct sdw_slave *slave,
2356c39710dSShuming Fan struct sdw_slave_intr_status *status)
2366c39710dSShuming Fan {
2376c39710dSShuming Fan struct rt712_sdca_priv *rt712 = dev_get_drvdata(&slave->dev);
2386c39710dSShuming Fan int ret, stat;
2396c39710dSShuming Fan int count = 0, retry = 3;
2406c39710dSShuming Fan unsigned int sdca_cascade, scp_sdca_stat1, scp_sdca_stat2 = 0;
2416c39710dSShuming Fan
2426c39710dSShuming Fan dev_dbg(&slave->dev,
2436c39710dSShuming Fan "%s control_port_stat=%x, sdca_cascade=%x", __func__,
2446c39710dSShuming Fan status->control_port, status->sdca_cascade);
2456c39710dSShuming Fan
2466c39710dSShuming Fan if (cancel_delayed_work_sync(&rt712->jack_detect_work)) {
2476c39710dSShuming Fan dev_warn(&slave->dev, "%s the pending delayed_work was cancelled", __func__);
2486c39710dSShuming Fan /* avoid the HID owner doesn't change to device */
2496c39710dSShuming Fan if (rt712->scp_sdca_stat2)
2506c39710dSShuming Fan scp_sdca_stat2 = rt712->scp_sdca_stat2;
2516c39710dSShuming Fan }
2526c39710dSShuming Fan
2536c39710dSShuming Fan /*
2546c39710dSShuming Fan * The critical section below intentionally protects a rather large piece of code.
2556c39710dSShuming Fan * We don't want to allow the system suspend to disable an interrupt while we are
2566c39710dSShuming Fan * processing it, which could be problematic given the quirky SoundWire interrupt
2576c39710dSShuming Fan * scheme. We do want however to prevent new workqueues from being scheduled if
2586c39710dSShuming Fan * the disable_irq flag was set during system suspend.
2596c39710dSShuming Fan */
2606c39710dSShuming Fan mutex_lock(&rt712->disable_irq_lock);
2616c39710dSShuming Fan
2626c39710dSShuming Fan ret = sdw_read_no_pm(rt712->slave, SDW_SCP_SDCA_INT1);
2636c39710dSShuming Fan if (ret < 0)
2646c39710dSShuming Fan goto io_error;
2656c39710dSShuming Fan rt712->scp_sdca_stat1 = ret;
2666c39710dSShuming Fan ret = sdw_read_no_pm(rt712->slave, SDW_SCP_SDCA_INT2);
2676c39710dSShuming Fan if (ret < 0)
2686c39710dSShuming Fan goto io_error;
2696c39710dSShuming Fan rt712->scp_sdca_stat2 = ret;
2706c39710dSShuming Fan if (scp_sdca_stat2)
2716c39710dSShuming Fan rt712->scp_sdca_stat2 |= scp_sdca_stat2;
2726c39710dSShuming Fan
2736c39710dSShuming Fan do {
2746c39710dSShuming Fan /* clear flag */
2756c39710dSShuming Fan ret = sdw_read_no_pm(rt712->slave, SDW_SCP_SDCA_INT1);
2766c39710dSShuming Fan if (ret < 0)
2776c39710dSShuming Fan goto io_error;
2786c39710dSShuming Fan if (ret & SDW_SCP_SDCA_INTMASK_SDCA_0) {
2796c39710dSShuming Fan ret = sdw_write_no_pm(rt712->slave, SDW_SCP_SDCA_INT1,
2806c39710dSShuming Fan SDW_SCP_SDCA_INTMASK_SDCA_0);
2816c39710dSShuming Fan if (ret < 0)
2826c39710dSShuming Fan goto io_error;
2836c39710dSShuming Fan }
2846c39710dSShuming Fan ret = sdw_read_no_pm(rt712->slave, SDW_SCP_SDCA_INT2);
2856c39710dSShuming Fan if (ret < 0)
2866c39710dSShuming Fan goto io_error;
2876c39710dSShuming Fan if (ret & SDW_SCP_SDCA_INTMASK_SDCA_8) {
2886c39710dSShuming Fan ret = sdw_write_no_pm(rt712->slave, SDW_SCP_SDCA_INT2,
2896c39710dSShuming Fan SDW_SCP_SDCA_INTMASK_SDCA_8);
2906c39710dSShuming Fan if (ret < 0)
2916c39710dSShuming Fan goto io_error;
2926c39710dSShuming Fan }
2936c39710dSShuming Fan
2946c39710dSShuming Fan /* check if flag clear or not */
2956c39710dSShuming Fan ret = sdw_read_no_pm(rt712->slave, SDW_DP0_INT);
2966c39710dSShuming Fan if (ret < 0)
2976c39710dSShuming Fan goto io_error;
2986c39710dSShuming Fan sdca_cascade = ret & SDW_DP0_SDCA_CASCADE;
2996c39710dSShuming Fan
3006c39710dSShuming Fan ret = sdw_read_no_pm(rt712->slave, SDW_SCP_SDCA_INT1);
3016c39710dSShuming Fan if (ret < 0)
3026c39710dSShuming Fan goto io_error;
3036c39710dSShuming Fan scp_sdca_stat1 = ret & SDW_SCP_SDCA_INTMASK_SDCA_0;
3046c39710dSShuming Fan
3056c39710dSShuming Fan ret = sdw_read_no_pm(rt712->slave, SDW_SCP_SDCA_INT2);
3066c39710dSShuming Fan if (ret < 0)
3076c39710dSShuming Fan goto io_error;
3086c39710dSShuming Fan scp_sdca_stat2 = ret & SDW_SCP_SDCA_INTMASK_SDCA_8;
3096c39710dSShuming Fan
3106c39710dSShuming Fan stat = scp_sdca_stat1 || scp_sdca_stat2 || sdca_cascade;
3116c39710dSShuming Fan
3126c39710dSShuming Fan count++;
3136c39710dSShuming Fan } while (stat != 0 && count < retry);
3146c39710dSShuming Fan
3156c39710dSShuming Fan if (stat)
3166c39710dSShuming Fan dev_warn(&slave->dev,
3176c39710dSShuming Fan "%s scp_sdca_stat1=0x%x, scp_sdca_stat2=0x%x\n", __func__,
3186c39710dSShuming Fan rt712->scp_sdca_stat1, rt712->scp_sdca_stat2);
3196c39710dSShuming Fan
3206c39710dSShuming Fan if (status->sdca_cascade && !rt712->disable_irq)
3216c39710dSShuming Fan mod_delayed_work(system_power_efficient_wq,
3226c39710dSShuming Fan &rt712->jack_detect_work, msecs_to_jiffies(30));
3236c39710dSShuming Fan
3246c39710dSShuming Fan mutex_unlock(&rt712->disable_irq_lock);
3256c39710dSShuming Fan
3266c39710dSShuming Fan return 0;
3276c39710dSShuming Fan
3286c39710dSShuming Fan io_error:
3296c39710dSShuming Fan mutex_unlock(&rt712->disable_irq_lock);
3306c39710dSShuming Fan pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
3316c39710dSShuming Fan return ret;
3326c39710dSShuming Fan }
3336c39710dSShuming Fan
3346c39710dSShuming Fan static struct sdw_slave_ops rt712_sdca_slave_ops = {
3356c39710dSShuming Fan .read_prop = rt712_sdca_read_prop,
3366c39710dSShuming Fan .interrupt_callback = rt712_sdca_interrupt_callback,
3376c39710dSShuming Fan .update_status = rt712_sdca_update_status,
3386c39710dSShuming Fan };
3396c39710dSShuming Fan
rt712_sdca_sdw_probe(struct sdw_slave * slave,const struct sdw_device_id * id)3406c39710dSShuming Fan static int rt712_sdca_sdw_probe(struct sdw_slave *slave,
3416c39710dSShuming Fan const struct sdw_device_id *id)
3426c39710dSShuming Fan {
3436c39710dSShuming Fan struct regmap *regmap, *mbq_regmap;
3446c39710dSShuming Fan
3456c39710dSShuming Fan /* Regmap Initialization */
3466c39710dSShuming Fan mbq_regmap = devm_regmap_init_sdw_mbq(slave, &rt712_sdca_mbq_regmap);
3476c39710dSShuming Fan if (IS_ERR(mbq_regmap))
3486c39710dSShuming Fan return PTR_ERR(mbq_regmap);
3496c39710dSShuming Fan
3506c39710dSShuming Fan regmap = devm_regmap_init_sdw(slave, &rt712_sdca_regmap);
3516c39710dSShuming Fan if (IS_ERR(regmap))
3526c39710dSShuming Fan return PTR_ERR(regmap);
3536c39710dSShuming Fan
3546c39710dSShuming Fan return rt712_sdca_init(&slave->dev, regmap, mbq_regmap, slave);
3556c39710dSShuming Fan }
3566c39710dSShuming Fan
rt712_sdca_sdw_remove(struct sdw_slave * slave)3576c39710dSShuming Fan static int rt712_sdca_sdw_remove(struct sdw_slave *slave)
3586c39710dSShuming Fan {
3596c39710dSShuming Fan struct rt712_sdca_priv *rt712 = dev_get_drvdata(&slave->dev);
3606c39710dSShuming Fan
3616c39710dSShuming Fan if (rt712->hw_init) {
3626c39710dSShuming Fan cancel_delayed_work_sync(&rt712->jack_detect_work);
3636c39710dSShuming Fan cancel_delayed_work_sync(&rt712->jack_btn_check_work);
3646c39710dSShuming Fan }
3656c39710dSShuming Fan
3666c39710dSShuming Fan pm_runtime_disable(&slave->dev);
3676c39710dSShuming Fan
3686c39710dSShuming Fan mutex_destroy(&rt712->calibrate_mutex);
3696c39710dSShuming Fan mutex_destroy(&rt712->disable_irq_lock);
3706c39710dSShuming Fan
3716c39710dSShuming Fan return 0;
3726c39710dSShuming Fan }
3736c39710dSShuming Fan
3746c39710dSShuming Fan static const struct sdw_device_id rt712_sdca_id[] = {
3756c39710dSShuming Fan SDW_SLAVE_ENTRY_EXT(0x025d, 0x712, 0x3, 0x1, 0),
3766c39710dSShuming Fan SDW_SLAVE_ENTRY_EXT(0x025d, 0x713, 0x3, 0x1, 0),
3776c39710dSShuming Fan SDW_SLAVE_ENTRY_EXT(0x025d, 0x716, 0x3, 0x1, 0),
3786c39710dSShuming Fan SDW_SLAVE_ENTRY_EXT(0x025d, 0x717, 0x3, 0x1, 0),
3796c39710dSShuming Fan {},
3806c39710dSShuming Fan };
3816c39710dSShuming Fan MODULE_DEVICE_TABLE(sdw, rt712_sdca_id);
3826c39710dSShuming Fan
rt712_sdca_dev_suspend(struct device * dev)3836c39710dSShuming Fan static int __maybe_unused rt712_sdca_dev_suspend(struct device *dev)
3846c39710dSShuming Fan {
3856c39710dSShuming Fan struct rt712_sdca_priv *rt712 = dev_get_drvdata(dev);
3866c39710dSShuming Fan
3876c39710dSShuming Fan if (!rt712->hw_init)
3886c39710dSShuming Fan return 0;
3896c39710dSShuming Fan
3906c39710dSShuming Fan cancel_delayed_work_sync(&rt712->jack_detect_work);
3916c39710dSShuming Fan cancel_delayed_work_sync(&rt712->jack_btn_check_work);
3926c39710dSShuming Fan
3936c39710dSShuming Fan regcache_cache_only(rt712->regmap, true);
3946c39710dSShuming Fan regcache_cache_only(rt712->mbq_regmap, true);
3956c39710dSShuming Fan
3966c39710dSShuming Fan return 0;
3976c39710dSShuming Fan }
3986c39710dSShuming Fan
rt712_sdca_dev_system_suspend(struct device * dev)3996c39710dSShuming Fan static int __maybe_unused rt712_sdca_dev_system_suspend(struct device *dev)
4006c39710dSShuming Fan {
4016c39710dSShuming Fan struct rt712_sdca_priv *rt712_sdca = dev_get_drvdata(dev);
4026c39710dSShuming Fan struct sdw_slave *slave = dev_to_sdw_dev(dev);
4036c39710dSShuming Fan int ret1, ret2;
4046c39710dSShuming Fan
4056c39710dSShuming Fan if (!rt712_sdca->hw_init)
4066c39710dSShuming Fan return 0;
4076c39710dSShuming Fan
4086c39710dSShuming Fan /*
4096c39710dSShuming Fan * prevent new interrupts from being handled after the
4106c39710dSShuming Fan * deferred work completes and before the parent disables
4116c39710dSShuming Fan * interrupts on the link
4126c39710dSShuming Fan */
4136c39710dSShuming Fan mutex_lock(&rt712_sdca->disable_irq_lock);
4146c39710dSShuming Fan rt712_sdca->disable_irq = true;
4156c39710dSShuming Fan ret1 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK1,
4166c39710dSShuming Fan SDW_SCP_SDCA_INTMASK_SDCA_0, 0);
4176c39710dSShuming Fan ret2 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK2,
4186c39710dSShuming Fan SDW_SCP_SDCA_INTMASK_SDCA_8, 0);
4196c39710dSShuming Fan mutex_unlock(&rt712_sdca->disable_irq_lock);
4206c39710dSShuming Fan
4216c39710dSShuming Fan if (ret1 < 0 || ret2 < 0) {
4226c39710dSShuming Fan /* log but don't prevent suspend from happening */
4236c39710dSShuming Fan dev_dbg(&slave->dev, "%s: could not disable SDCA interrupts\n:", __func__);
4246c39710dSShuming Fan }
4256c39710dSShuming Fan
4266c39710dSShuming Fan return rt712_sdca_dev_suspend(dev);
4276c39710dSShuming Fan }
4286c39710dSShuming Fan
4296c39710dSShuming Fan #define RT712_PROBE_TIMEOUT 5000
4306c39710dSShuming Fan
rt712_sdca_dev_resume(struct device * dev)4316c39710dSShuming Fan static int __maybe_unused rt712_sdca_dev_resume(struct device *dev)
4326c39710dSShuming Fan {
4336c39710dSShuming Fan struct sdw_slave *slave = dev_to_sdw_dev(dev);
4346c39710dSShuming Fan struct rt712_sdca_priv *rt712 = dev_get_drvdata(dev);
4356c39710dSShuming Fan unsigned long time;
4366c39710dSShuming Fan
4376c39710dSShuming Fan if (!rt712->first_hw_init)
4386c39710dSShuming Fan return 0;
4396c39710dSShuming Fan
4407a8735c1SShuming Fan if (!slave->unattach_request) {
4417a8735c1SShuming Fan mutex_lock(&rt712->disable_irq_lock);
442*10641083SPierre-Louis Bossart if (rt712->disable_irq == true) {
443*10641083SPierre-Louis Bossart
4447a8735c1SShuming Fan sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
4457a8735c1SShuming Fan sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
4467a8735c1SShuming Fan rt712->disable_irq = false;
4477a8735c1SShuming Fan }
448*10641083SPierre-Louis Bossart mutex_unlock(&rt712->disable_irq_lock);
4496c39710dSShuming Fan goto regmap_sync;
4507a8735c1SShuming Fan }
4516c39710dSShuming Fan
4526c39710dSShuming Fan time = wait_for_completion_timeout(&slave->initialization_complete,
4536c39710dSShuming Fan msecs_to_jiffies(RT712_PROBE_TIMEOUT));
4546c39710dSShuming Fan if (!time) {
4556c39710dSShuming Fan dev_err(&slave->dev, "Initialization not complete, timed out\n");
4566c39710dSShuming Fan sdw_show_ping_status(slave->bus, true);
4576c39710dSShuming Fan
4586c39710dSShuming Fan return -ETIMEDOUT;
4596c39710dSShuming Fan }
4606c39710dSShuming Fan
4616c39710dSShuming Fan regmap_sync:
4626c39710dSShuming Fan slave->unattach_request = 0;
4636c39710dSShuming Fan regcache_cache_only(rt712->regmap, false);
4646c39710dSShuming Fan regcache_sync(rt712->regmap);
4656c39710dSShuming Fan regcache_cache_only(rt712->mbq_regmap, false);
4666c39710dSShuming Fan regcache_sync(rt712->mbq_regmap);
4676c39710dSShuming Fan return 0;
4686c39710dSShuming Fan }
4696c39710dSShuming Fan
4706c39710dSShuming Fan static const struct dev_pm_ops rt712_sdca_pm = {
4716c39710dSShuming Fan SET_SYSTEM_SLEEP_PM_OPS(rt712_sdca_dev_system_suspend, rt712_sdca_dev_resume)
4726c39710dSShuming Fan SET_RUNTIME_PM_OPS(rt712_sdca_dev_suspend, rt712_sdca_dev_resume, NULL)
4736c39710dSShuming Fan };
4746c39710dSShuming Fan
4756c39710dSShuming Fan static struct sdw_driver rt712_sdca_sdw_driver = {
4766c39710dSShuming Fan .driver = {
4776c39710dSShuming Fan .name = "rt712-sdca",
4786c39710dSShuming Fan .owner = THIS_MODULE,
4796c39710dSShuming Fan .pm = &rt712_sdca_pm,
4806c39710dSShuming Fan },
4816c39710dSShuming Fan .probe = rt712_sdca_sdw_probe,
4826c39710dSShuming Fan .remove = rt712_sdca_sdw_remove,
4836c39710dSShuming Fan .ops = &rt712_sdca_slave_ops,
4846c39710dSShuming Fan .id_table = rt712_sdca_id,
4856c39710dSShuming Fan };
4866c39710dSShuming Fan module_sdw_driver(rt712_sdca_sdw_driver);
4876c39710dSShuming Fan
4886c39710dSShuming Fan MODULE_DESCRIPTION("ASoC RT712 SDCA SDW driver");
4896c39710dSShuming Fan MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>");
4906c39710dSShuming Fan MODULE_LICENSE("GPL");
491