[PATCH 2/4] ALSA: hda: intel-nhlt: add intel_nhlt_ssp_mclk_mask()
Amadeusz Sławiński
amadeuszx.slawinski at linux.intel.com
Tue Aug 23 16:55:55 CEST 2022
On 8/23/2022 10:52 AM, Pierre-Louis Bossart wrote:
> Hi Amadeusz,
>
>>> +int intel_nhlt_ssp_mclk_mask(struct nhlt_acpi_table *nhlt, int ssp_num)
>>> +{
>>> + struct nhlt_endpoint *epnt;
>>> + struct nhlt_fmt *fmt;
>>> + struct nhlt_fmt_cfg *cfg;
>>> + int mclk_mask = 0;
>>> + int i, j;
>>> +
>>> + if (!nhlt)
>>> + return 0;
>>> +
>>> + epnt = (struct nhlt_endpoint *)nhlt->desc;
>>> + for (i = 0; i < nhlt->endpoint_count; i++) {
>>> +
>>> + /* we only care about endpoints connected to an audio codec
>>> over SSP */
>>> + if (epnt->linktype == NHLT_LINK_SSP &&
>>> + epnt->device_type == NHLT_DEVICE_I2S &&
>>> + epnt->virtual_bus_id == ssp_num) {
>>
>> if (epnt->linktype != NHLT_LINK_SSP ||
>> epnt->device_type != NHLT_DEVICE_I2S ||
>> epnt->virtual_bus_id != ssp_num)
>> continue;
>>
>> and then you can remove one indentation level below?
>
>
> Would that work? We still need to move the epnt pointer:
>
> epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
>
> and moving this in the endpoint_count loop would be ugly as well.
>
>
Another solution would be goto to skip, but that also seems ugly :/
I guess it can stay as it is then.
>>> +
>>> + fmt = (struct nhlt_fmt *)(epnt->config.caps +
>>> epnt->config.size);
>>> + cfg = fmt->fmt_config;
>>> +
>>> + /*
>>> + * In theory all formats should use the same MCLK but it
>>> doesn't hurt to
>>> + * double-check that the configuration is consistent
>>> + */
>>> + for (j = 0; j < fmt->fmt_count; j++) {
>>> + u32 *blob;
>>> + int mdivc_offset;
>>> +
>>> + if (cfg->config.size >= SSP_BLOB_V1_0_SIZE) {
>>> + blob = (u32 *)cfg->config.caps;
>>> +
>>> + if (blob[1] == SSP_BLOB_VER_2_0)
>>> + mdivc_offset = SSP_BLOB_V2_0_MDIVC_OFFSET;
>>> + else if (blob[1] == SSP_BLOB_VER_1_5)
>>> + mdivc_offset = SSP_BLOB_V1_5_MDIVC_OFFSET;
>>> + else
>>> + mdivc_offset = SSP_BLOB_V1_0_MDIVC_OFFSET;
>>> +
>>> + mclk_mask |= blob[mdivc_offset] & GENMASK(1, 0);
One more thing, where does this GENMASK come from, as far as I can tell
HW specifies and FW uses one bit field to signal that MCLK is enabled?
(mdivc is simply a value written to HW register to configure it).
>>> + }
>>> +
>>> + cfg = (struct nhlt_fmt_cfg *)(cfg->config.caps +
>>> cfg->config.size);
>>> + }
>>> + }
>>> + epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
>>> + }
>>> +
>>> + return mclk_mask;
>>
>> Although I understand that it is relegated to the caller, but if both
>> mclk being set is considered an error maybe add some kind of check here
>> instead and free callers from having to remember about it?
>>
>> if (hweight_long(mclk_mask) != 1)
>> return -EINVAL;
>>
>> return mclk_mask;
>
> I went back and forth multiple times on this one. I can't figure out if
> this would be a bug or a feature, it could be e.g. a test capability and
> it's supported in hardware. I decided to make the decision in the caller
> rather than a lower level in the library.
>
> If the tools used to generate NHLT don't support this multi-MCLK mode
> then we could indeed move the test here.
>
Considering comment I added above I've asked Czarek to also check this
series. I'm not sure it even makes sense to name the field "_mask" when
it is one bit...
>>
>>> +}
>>> +EXPORT_SYMBOL(intel_nhlt_ssp_mclk_mask);
>>> +
>>> static struct nhlt_specific_cfg *
>>> nhlt_get_specific_cfg(struct device *dev, struct nhlt_fmt *fmt, u8
>>> num_ch,
>>> u32 rate, u8 vbps, u8 bps)
>>
More information about the Alsa-devel
mailing list