Linux Sound subsystem development
 help / color / mirror / Atom feed
From: "Shuming [范書銘]" <shumingf@realtek.com>
To: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>,
	"broonie@kernel.org" <broonie@kernel.org>,
	"lgirdwood@gmail.com" <lgirdwood@gmail.com>
Cc: "linux-sound@vger.kernel.org" <linux-sound@vger.kernel.org>,
	"lars@metafoo.de" <lars@metafoo.de>,
	"Flove(HsinFu)" <flove@realtek.com>,
	"Oder Chiou" <oder_chiou@realtek.com>,
	"Jack Yu" <jack.yu@realtek.com>,
	"Derek [方德義]" <derek.fang@realtek.com>,
	"Charles Keepax" <ckeepax@opensource.cirrus.com>
Subject: RE: [PATCH] ASoC: rt766: add RT766/RT767 SDCA driver
Date: Tue, 21 Jul 2026 07:09:21 +0000	[thread overview]
Message-ID: <86960974a5bd488eb0e1a44130cbaa21@realtek.com> (raw)
In-Reply-To: <fff6c488-295d-47c3-819a-478b6dc3b24b@linux.dev>

> > This patch adds the initial SDCA multi-function codec driver for the RT766
> and RT767.
> >
> > Signed-off-by: Shuming Fan <shumingf@realtek.com>
> 
> Looks mostly good, I only have minor comments, see below.

Thanks for the review.

> > +static bool rt766_sdca_readable_register(struct device *dev, unsigned
> > +int reg) {
> > +     switch (reg) {
> > +     case SDW_SCP_SDCA_INT1 ... SDW_SCP_SDCA_INTMASK4:
> > +     case RT766_VERSION_ID ... RT766_BOND_LATCH_ID:
> > +     case 0xc344 ... 0xc345:
> > +     case 0xc900:
> > +     case 0xc920:
> > +     case 0xd540 ... 0xd542:
> > +     case 0xf01e:
> > +     case RT766_HP_POWER_STATE ... RT766_HP_FSM_CTL2_1:
> > +     case 0x310100:
> > +     case RT766_MCU_PATCH_ADDR1_START ...
> RT766_MCU_PATCH_ADDR1_END:
> > +     case RT766_MCU_PATCH_ADDR2_START ...
> RT766_MCU_PATCH_ADDR2_END:
> > +     case RT766_MUTE_REG(UAJ, USER_FU41, 1):
> > +     case RT766_MUTE_REG(UAJ, USER_FU41, 2):
> > +     case RT766_VOLUME_REG(UAJ, USER_FU41, 1):
> > +     case RT766_VOLUME_REG(UAJ, USER_FU41, 2):
> > +     case RT766_MUTE_REG(UAJ, USER_FU36, 1):
> > +     case RT766_MUTE_REG(UAJ, USER_FU36, 2):
> > +     case RT766_VOLUME_REG(UAJ, USER_FU36, 1):
> > +     case RT766_VOLUME_REG(UAJ, USER_FU36, 2):
> > +     case RT766_PDE_REQ_REG(UAJ, PDE47):
> > +     case RT766_PDE_REQ_REG(UAJ, PDE34):
> > +     case RT766_SDCA_CTL(UAJ, CS41,
> SDCA_CTL_CS_SAMPLERATEINDEX):
> > +     case RT766_SDCA_CTL(UAJ, CS36,
> SDCA_CTL_CS_SAMPLERATEINDEX):
> > +     /* 0x40480000 */
> > +     case RT766_FUNC_STATUS_REG(UAJ):
> > +     /* 0x40481400 */
> > +     case RT766_PDE_ACTUAL_REG(UAJ, PDE47):
> > +     /* 0x40481480 */
> 
> these single line registers listed in comments confuse me, not clear for
> example if this one applies to the following line...

Sorry these address comments caused any confusion. These address comments help me put the code in address order.
I will apply single address comment to the following line.

> > +     case RT766_PDE_ACTUAL_REG(UAJ, PDE34):
> 
> but then why not adde the values for the next 3?

Those registers have the comment in the rt766_sdca_defaults.

> > +     case RT766_GAIN_REG(UAJ, PLATFORM_FU33, 1):
> > +     case RT766_GAIN_REG(UAJ, PLATFORM_FU33, 2):
> > +     case RT766_SDCA_CTL(UAJ, GE49,
> SDCA_CTL_GE_SELECTED_MODE):
> > +     /* 0x40600490 */
> > +     case RT766_SDCA_CTL(UAJ, GE49,
> SDCA_CTL_GE_DETECTED_MODE):
> > +     case RT766_PDE_REQ_REG(MIC, PDE11):
> > +     case RT766_MUTE_REG(MIC, USER_FU113, 1):
> > +     case RT766_MUTE_REG(MIC, USER_FU113, 2):
> > +     case RT766_MUTE_REG(MIC, USER_FU113, 3):
> > +     case RT766_MUTE_REG(MIC, USER_FU113, 4):
> > +     case RT766_VOLUME_REG(MIC, USER_FU113, 1):
> > +     case RT766_VOLUME_REG(MIC, USER_FU113, 2):
> > +     case RT766_VOLUME_REG(MIC, USER_FU113, 3):
> > +     case RT766_VOLUME_REG(MIC, USER_FU113, 4):
> > +     /* 0x40880000 */
> > +     case RT766_FUNC_STATUS_REG(MIC):
> 
> same here, are 0x40880000  and RT766_FUNC_STATUS_REG equivalent? If
> yes maybe move the comment to the right side?
> 
> > +     case RT766_SDCA_CTL(MIC, CS113,
> SDCA_CTL_CS_SAMPLERATEINDEX):
> > +     /* 0x40881500 */
> > +     case RT766_PDE_ACTUAL_REG(MIC, PDE11):
> > +     /* 0x40c80000 */
> > +     case RT766_FUNC_STATUS_REG(HID):
> > +     /* 0x40c80080 - 0x40c80098 */
> > +     case RT766_SDCA_CTL(HID, HID101,
> SDCA_CTL_HIDE_HIDTX_CURRENTOWNER) ...
> > +             RT766_SDCA_CTL(HID, HID101,
> SDCA_CTL_HIDE_HIDTX_MESSAGELENGTH):
> > +     case RT766_MUTE_REG(AMP, USER_FU21, 1):
> > +     case RT766_MUTE_REG(AMP, USER_FU21, 2):
> > +     case RT766_VOLUME_REG(AMP, USER_FU21, 1):
> > +     case RT766_VOLUME_REG(AMP, USER_FU21, 2):
> > +     case RT766_PDE_REQ_REG(AMP, PDE23):
> > +     /* 0x41080000 */
> > +     case RT766_FUNC_STATUS_REG(AMP):
> > +     case RT766_SDCA_CTL(AMP, PPU21,
> SDCA_CTL_PPU_POSTURENUMBER):
> > +     case RT766_SDCA_CTL(AMP, CS21,
> SDCA_CTL_CS_SAMPLERATEINDEX):
> > +     /* 0x41081980 */
> > +     case RT766_PDE_ACTUAL_REG(AMP, PDE23):
> > +     case RT766_BUF_ADDR_HID1 ... RT766_BUF_ADDR_HID2:
> > +             return true;
> > +     default:
> > +             return false;
> > +     }
> > +}
> 
> > +static const struct reg_default rt766_sdca_defaults[] = {
> > +     /* 0x40400289 - 0x4040028a */
> > +     { RT766_MUTE_REG(UAJ, USER_FU41, 1), 0x01 },
> > +     { RT766_MUTE_REG(UAJ, USER_FU41, 2), 0x01 },
> 
> things are much clearer/organized here!
> 
> > +     /* 0x40400291 - 0x40400292 */
> > +     { RT766_VOLUME_REG(UAJ, USER_FU41, 1), 0x0000 },
> > +     { RT766_VOLUME_REG(UAJ, USER_FU41, 2), 0x0000 },
> > +     /* 0x40400789 - 0x4040078a */
> > +     { RT766_MUTE_REG(UAJ, USER_FU36, 1), 0x01 },
> > +     { RT766_MUTE_REG(UAJ, USER_FU36, 2), 0x01 },
> > +     /* 0x40400791 - 0x40400792 */
> > +     { RT766_VOLUME_REG(UAJ, USER_FU36, 1), 0x0000 },
> > +     { RT766_VOLUME_REG(UAJ, USER_FU36, 2), 0x0000 },
> > +     /* 0x40401408 */
> > +     { RT766_PDE_REQ_REG(UAJ, PDE47), 0x03 },
> > +     /* 0x40401488 */
> > +     { RT766_PDE_REQ_REG(UAJ, PDE34), 0x03 },
> > +     /* 0x40480080 */
> > +     { RT766_SDCA_CTL(UAJ, CS41, SDCA_CTL_CS_SAMPLERATEINDEX),
> 0x09 },
> > +     /* 0x40480880 */
> > +     { RT766_SDCA_CTL(UAJ, CS36, SDCA_CTL_CS_SAMPLERATEINDEX),
> 0x09 },
> > +     /* 0x40600259 - 0x4060025a */
> > +     { RT766_GAIN_REG(UAJ, PLATFORM_FU33, 1), 0xfe00 },
> > +     { RT766_GAIN_REG(UAJ, PLATFORM_FU33, 2), 0xfe00 },
> > +     /* 0x40600488 */
> > +     { RT766_SDCA_CTL(UAJ, GE49, SDCA_CTL_GE_SELECTED_MODE),
> 0x00 },
> 
> > +static struct sdca_entity *rt766_find_entity_by_label(struct
> sdca_function_data *func,
> > +     const char *label)
> > +{
> > +     struct sdca_entity *entity = NULL;
> 
> useless initialization?

Will export find_sdca_entity_by_label() instead.

> > +     int idx;
> > +
> > +     for (idx = 0; idx < func->num_entities; idx++) {
> > +             entity = &func->entities[idx];
> > +
> > +             if (!strcmp(entity->label, label))
> > +                     return entity;
> > +     }
> > +
> > +     return NULL;
> > +}
> 
> > +static int rt766_sdca_irq_ctl(struct rt766_sdca_priv *rt766,
> > +                                                       struct
> sdca_function_data *function,
> > +                                                       struct
> snd_soc_component *component,
> > +                                                       struct
> sdca_interrupt_info *info,
> > +                                                       bool
> enabled)
> > +{
> > +     struct device *dev = &rt766->slave->dev;
> > +     struct sdca_interrupt *interrupt;
> > +     struct sdca_control *control;
> > +     struct sdca_entity *entity;
> > +     irq_handler_t handler;
> > +     int i, j, irq, ret;
> > +
> > +     for (i = 0; i < function->num_entities; i++) {
> > +             entity = &function->entities[i];
> > +
> > +             for (j = 0; j < entity->num_controls; j++) {
> > +                     control = &entity->controls[j];
> > +                     irq = control->interrupt_position;
> > +
> > +                     switch (SDCA_CTL_TYPE(entity->type,
> control->sel)) {
> > +                     case SDCA_CTL_TYPE_S(GE, DETECTED_MODE):
> > +                             handler = rt766_sdca_irq_jd_handler;
> > +                             break;
> > +                     case SDCA_CTL_TYPE_S(HIDE,
> HIDTX_CURRENTOWNER):
> > +                             handler = rt766_sdca_irq_btn_handler;
> > +                             break;
> > +                     default:
> > +                             continue;
> > +                     }
> > +
> > +                     interrupt = &info->irqs[irq];
> > +
> > +                     if (enabled) {
> > +                             ret = sdca_irq_data_populate(dev,
> rt766->regmap, component,
> > +
> function, entity, control,
> > +
> interrupt);
> > +                             if (ret)
> > +                                     return ret;
> > +
> > +                             interrupt->priv = rt766;
> > +                             ret = sdca_irq_request(dev, info, irq,
> interrupt->name,
> > +
> handler,
> > + interrupt);
> 
> There was a proposal from Charles to do an irq_populate_early, is there a
> conflict between the two patchsets? see "ASoC: SDCA: Populate IRQ data
> earlier"

Will check with Charles.

> > +                             if (ret) {
> > +                                     dev_err(dev, "failed to
> request irq %s: %d\n",
> > +                                             interrupt->name,
> ret);
> > +                                     return ret;
> > +                             }
> > +                             dev_dbg(dev, "Requesting IRQ %d
> InterruptName=%s\n", irq, interrupt->name);
> > +                     } else {
> > +                             sdca_irq_free(dev, info, irq,
> interrupt->name, interrupt);
> > +                             dev_dbg(dev, "Freeing IRQ %d\n", irq);
> > +                     }
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> 
> > +static int rt766_sdca_set_fu41_playback_ctl(struct rt766_sdca_priv
> > +*rt766) {
> > +     int err;
> > +     unsigned int ch_01, ch_02;
> 
> nit-pick: likely copy/paste from other drivers, but flipping the two lines would
> be nicer. there are a couple of similar patterns in this driver.

Sure, will fix.

> > +
> > +     ch_01 = (rt766->fu41_dapm_mute || rt766->fu41_mixer_l_mute) ?
> 0x01 : 0x00;
> > +     ch_02 = (rt766->fu41_dapm_mute || rt766->fu41_mixer_r_mute) ?
> > + 0x01 : 0x00;
> > +
> > +     err = regmap_write(rt766->regmap, RT766_MUTE_REG(UAJ,
> USER_FU41, 1), ch_01);
> > +     if (err < 0)
> > +             return err;
> > +
> > +     err = regmap_write(rt766->regmap, RT766_MUTE_REG(UAJ,
> USER_FU41, 2), ch_02);
> > +     if (err < 0)
> > +             return err;
> > +
> > +     return 0;
> > +}
> 
> > +static int rt766_sdca_pde47_event(struct snd_soc_dapm_widget *w,
> > +     struct snd_kcontrol *kcontrol, int event) {
> > +     struct snd_soc_component *component =
> snd_soc_dapm_to_component(w->dapm);
> > +     struct rt766_sdca_priv *rt766 =
> snd_soc_component_get_drvdata(component);
> > +     const struct sdca_entity *entity = NULL;
> 
> useless init?

Will fix.

> > +     unsigned char ps0 = 0x0, ps3 = 0x3;
> > +     int from_ps, to_ps;
> > +     int ret;
> > +
> > +     switch (event) {
> > +     case SND_SOC_DAPM_POST_PMU:
> > +             regmap_write(rt766->regmap, RT766_PDE_REQ_REG(UAJ,
> PDE47), ps0);
> > +             from_ps = ps3;
> > +             to_ps = ps0;
> > +             break;
> > +     case SND_SOC_DAPM_PRE_PMD:
> > +             regmap_write(rt766->regmap, RT766_PDE_REQ_REG(UAJ,
> PDE47), ps3);
> > +             from_ps = ps0;
> > +             to_ps = ps3;
> > +             break;
> > +     }
> > +
> > +     entity = rt766_find_entity_by_label(rt766->uaj_func_data, "PDE 47");
> > +     ret = sdca_asoc_pde_poll_actual_ps(component->dev,
> rt766->regmap,
> > +                                RT766_FUNC_NUM_UAJ,
> > +                                RT766_SDCA_ENT_PDE47,
> > +                                from_ps, to_ps,
> > +                                entity ? entity->pde.max_delay :
> NULL,
> > +                                entity ?
> entity->pde.num_max_delay : 0);
> > +     if (ret)
> > +             dev_err(component->dev, "%s: PDE transition %x -> %x
> failed, err=%d\n",
> > +                     __func__, from_ps, to_ps, ret);
> > +
> > +     return ret;
> > +}
> 
> > +static int rt766_sdca_pde34_event(struct snd_soc_dapm_widget *w,
> > +     struct snd_kcontrol *kcontrol, int event) {
> > +     struct snd_soc_component *component =
> snd_soc_dapm_to_component(w->dapm);
> > +     struct rt766_sdca_priv *rt766 =
> snd_soc_component_get_drvdata(component);
> > +     const struct sdca_entity *entity = NULL;
> 
> useless init? Same comment for all PDE events.
> 
> > +     unsigned char ps0 = 0x0, ps3 = 0x3;
> > +     int from_ps, to_ps;
> > +     int ret;
> > +
> > +     switch (event) {
> > +     case SND_SOC_DAPM_POST_PMU:
> > +             regmap_write(rt766->regmap, RT766_PDE_REQ_REG(UAJ,
> PDE34), ps0);
> > +             from_ps = ps3;
> > +             to_ps = ps0;
> > +             break;
> > +     case SND_SOC_DAPM_PRE_PMD:
> > +             regmap_write(rt766->regmap, RT766_PDE_REQ_REG(UAJ,
> PDE34), ps3);
> > +             from_ps = ps0;
> > +             to_ps = ps3;
> > +             break;
> > +     }
> > +
> > +     entity = rt766_find_entity_by_label(rt766->uaj_func_data, "PDE 34");
> > +     ret = sdca_asoc_pde_poll_actual_ps(component->dev,
> rt766->regmap,
> > +                                RT766_FUNC_NUM_UAJ,
> > +                                RT766_SDCA_ENT_PDE34,
> > +                                from_ps, to_ps,
> > +                                entity ? entity->pde.max_delay :
> NULL,
> > +                                entity ?
> entity->pde.num_max_delay : 0);
> > +     if (ret)
> > +             dev_err(component->dev, "%s: PDE transition %x -> %x
> failed, err=%d\n",
> > +                     __func__, from_ps, to_ps, ret);
> > +
> > +     return ret;
> > +}
> 
> 
> > +static int rt766_sdca_probe(struct snd_soc_component *component) {
> > +     struct rt766_sdca_priv *rt766 =
> snd_soc_component_get_drvdata(component);
> > +     struct device *dev = &rt766->slave->dev;
> > +     int ret;
> > +
> > +     rt766->component = component;
> > +
> > +     ret = pm_runtime_resume(component->dev);
> > +     if (ret < 0 && ret != -EACCES)
> > +             return ret;
> > +
> > +     if (rt766->uaj_func_data) {
> > +             dev_dbg(dev, "%s : irq %d\n", __func__,
> > + rt766->slave->irq);
> > +
> > +             rt766->irq_info = sdca_irq_allocate(dev, rt766->regmap,
> rt766->slave->irq);
> > +             if (IS_ERR(rt766->irq_info))
> > +                     return PTR_ERR(rt766->irq_info);
> > +
> > +             ret = rt766_sdca_irq_ctl(rt766, rt766->uaj_func_data,
> > +                     component, rt766->irq_info, true);
> 
> same question on IRQ allocate/request for Charles.
> 
> > +             if (ret < 0) {
> > +                     dev_err(dev, "Failed to request UAJ SDCA IRQ:
> %d\n", ret);
> > +                     return ret;
> > +             }
> > +
> > +             if (rt766->hid_func_data) {
> > +                     ret = rt766_sdca_irq_ctl(rt766,
> rt766->hid_func_data,
> > +                             component, rt766->irq_info, true);
> > +                     if (ret < 0) {
> > +                             dev_err(dev, "Failed to request HID
> SDCA IRQ: %d\n", ret);
> > +                             return ret;
> > +                     }
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> 
> > +static unsigned int rt766_find_dt_rates(struct device *dev, struct
> sdca_function_data *function,
> > +                                                     const char
> > +*label) {
> > +     struct sdca_entity *entity = NULL;
> 
> useless init?
> 
> > +     unsigned int rates;
> > +     int i, ret;
> > +
> > +     for (i = 0; i < function->num_entities; i++) {
> > +             entity = &function->entities[i];
> > +
> > +             if (strcmp(entity->label, label))
> > +                     continue;
> > +
> > +             /* Can't check earlier as only terminals have an iot
> member. */
> > +             if (!entity->iot.is_dataport)
> > +                     continue;
> > +
> > +             ret = rt766_parse_rates(dev, function, entity, &rates);
> > +             if (ret < 0) {
> > +                     dev_dbg(dev, "%s: failed to parse rates for entity
> %s\n",
> > +                             __func__, entity->label);
> > +                     return 0;
> > +             }
> > +
> > +             dev_dbg(dev, "%s: %s supports rates 0x%08x\n", __func__,
> entity->label, rates);
> > +     }
> > +
> > +     return rates;
> > +}
> > +
> > +int rt766_sdca_init(struct device *dev, struct regmap *regmap, struct
> > +sdw_slave *slave) {
> > +     struct sdca_function_data *func_data_ptr;
> > +     struct rt766_sdca_priv *rt766;
> > +     unsigned int rates;
> > +     int ret;
> > +     int i;
> > +
> > +     rt766 = devm_kzalloc(dev, sizeof(*rt766), GFP_KERNEL);
> > +     if (!rt766)
> > +             return -ENOMEM;
> > +
> > +     dev_set_drvdata(dev, rt766);
> > +     rt766->slave = slave;
> > +     rt766->regmap = regmap;
> > +
> > +     regcache_cache_only(rt766->regmap, true);
> > +
> > +     mutex_init(&rt766->disable_irq_lock);
> > +
> > +     /*
> > +      * Mark hw_init to false
> > +      * HW init will be performed when device reports present
> > +      */
> > +     rt766->hw_init = false;
> > +     rt766->first_hw_init = false;
> > +     rt766->fu41_dapm_mute = true;
> > +     rt766->fu41_mixer_l_mute = rt766->fu41_mixer_r_mute = false;
> > +     rt766->fu36_dapm_mute = true;
> > +     rt766->fu36_mixer_l_mute = rt766->fu36_mixer_r_mute = true;
> > +     rt766->fu21_dapm_mute = true;
> > +     rt766->fu21_mixer_l_mute = rt766->fu21_mixer_r_mute = false;
> > +     rt766->fu113_dapm_mute = true;
> > +     rt766->fu113_mixer_mute[0] = rt766->fu113_mixer_mute[1] =
> > +             rt766->fu113_mixer_mute[2] =
> rt766->fu113_mixer_mute[3]
> > + = true;
> > +
> > +     /* get SDCA function data */
> > +     dev_dbg(dev, "SDCA functions found: %d",
> slave->sdca_data.num_functions);
> > +     for (i = 0; i < slave->sdca_data.num_functions; i++) {
> > +             func_data_ptr = devm_kzalloc(dev, sizeof(*func_data_ptr),
> GFP_KERNEL);
> > +             if (!func_data_ptr)
> > +                     return dev_err_probe(dev, -ENOMEM, "failed to
> > + allocate function data");
> > +
> > +             func_data_ptr->desc = &slave->sdca_data.function[i];
> > +             ret = sdca_parse_function(dev, slave, func_data_ptr);
> > +             if (ret) {
> > +                     devm_kfree(dev, func_data_ptr);
> > +                     return ret;
> > +             }
> > +             dev_dbg(dev, "Function type=%d, num_entities=%d",
> > +                     slave->sdca_data.function[i].type,
> > + func_data_ptr->num_entities);
> > +
> > +             switch (slave->sdca_data.function[i].type) {
> > +             case SDCA_FUNCTION_TYPE_UAJ:
> > +                     rt766->uaj_func_data = func_data_ptr;
> > +                     /*
> > +                      * Some machines may only support a subset of
> the sample rates supported by the codec.
> > +                      * Therefore, we need to parse the supported
> sample rates from the DisCo table and
> > +                      * configure them in the DAI. If the DisCo table
> does not provide sample rate information,
> > +                      * we will fall back to the default supported rates
> defined in the codec driver.
> > +                      */
> > +                     rates = rt766_find_dt_rates(dev, func_data_ptr,
> "IT 41");
> > +                     if (rates)
> > +                             rt766_sdca_dai[0].playback.rates =
> > + rates;
> > +
> > +                     rates = rt766_find_dt_rates(dev, func_data_ptr,
> "OT 36");
> > +                     if (rates)
> > +                             rt766_sdca_dai[0].capture.rates =
> rates;
> > +                     break;
> > +             case SDCA_FUNCTION_TYPE_SMART_AMP:
> > +                     rt766->sa_func_data = func_data_ptr;
> > +                     rates = rt766_find_dt_rates(dev, func_data_ptr,
> "IT 21");
> > +                     if (rates)
> > +                             rt766_sdca_dai[1].playback.rates =
> rates;
> > +                     break;
> > +             case SDCA_FUNCTION_TYPE_SMART_MIC:
> > +                     rt766->sm_func_data = func_data_ptr;
> > +                     rates = rt766_find_dt_rates(dev, func_data_ptr,
> "OT 113");
> > +                     if (rates)
> > +                             rt766_sdca_dai[2].capture.rates =
> rates;
> 
> are the sdca_dai[index] related to the function? Wondering if we can use e.g
> sdca_dai[MIC] instead?

Sure, will use the enumeration value.

> > +                     break;
> > +             case SDCA_FUNCTION_TYPE_HID:
> > +                     rt766->hid_func_data = func_data_ptr;
> > +                     break;
> > +             default:
> > +                     dev_dbg(dev, "Unexpected SDCA function type
> found: %d",
> > +                             slave->sdca_data.function[i].type);
> > +             }
> > +     }
> > +
> > +     ret =  devm_snd_soc_register_component(dev,
> > +                     &soc_sdca_dev_rt766, rt766_sdca_dai,
> ARRAY_SIZE(rt766_sdca_dai));
> > +     if (ret < 0)
> > +             return ret;
> > +
> > +     /* set autosuspend parameters */
> > +     pm_runtime_set_autosuspend_delay(dev, 3000);
> > +     pm_runtime_use_autosuspend(dev);
> > +
> > +     /* make sure the device does not suspend immediately */
> > +     pm_runtime_mark_last_busy(dev);
> > +
> > +     pm_runtime_enable(dev);
> > +
> > +     dev_dbg(dev, "%s\n", __func__);
> > +
> > +     return 0;
> > +}
> 


  reply	other threads:[~2026-07-21  7:09 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-20  9:06 [PATCH] ASoC: rt766: add RT766/RT767 SDCA driver shumingf
2026-07-20 14:38 ` Pierre-Louis Bossart
2026-07-21  7:09   ` Shuming [范書銘] [this message]
2026-07-20 16:21 ` Charles Keepax
2026-07-21  7:10   ` Shuming [范書銘]
2026-07-21 10:29     ` Charles Keepax

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=86960974a5bd488eb0e1a44130cbaa21@realtek.com \
    --to=shumingf@realtek.com \
    --cc=broonie@kernel.org \
    --cc=ckeepax@opensource.cirrus.com \
    --cc=derek.fang@realtek.com \
    --cc=flove@realtek.com \
    --cc=jack.yu@realtek.com \
    --cc=lars@metafoo.de \
    --cc=lgirdwood@gmail.com \
    --cc=linux-sound@vger.kernel.org \
    --cc=oder_chiou@realtek.com \
    --cc=pierre-louis.bossart@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox