Skip to content

ASoC: SOF: add DAI clock driver - #2932

Closed
brentlu wants to merge 1 commit into
thesofproject:topic/sof-devfrom
brentlu:dai_clk_driver
Closed

brentlu wants to merge 1 commit into
thesofproject:topic/sof-devfrom
brentlu:dai_clk_driver

Conversation

@brentlu

@brentlu brentlu commented May 19, 2021

Copy link
Copy Markdown

A virtual clock driver is added to SOF platform driver. Machine driver
could use the clock interface to send IPCs to SOF FW to enable/disable
the clocks.

Signed-off-by: Brent Lu brent.lu@intel.com


init.name = pdata->dai_clks[i].name;
init.ops = &sof_clk_ops;
init.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_GATE;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem here is I don't know the correct flag for the virtual clock. Need expert to comment the flag.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not an expert in the clock API, but how about 0? :-) So far this clock doesn't even change rate, so why cannot it be cached?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RATE_GATE might be valid for SCLK they tend to like being stopped in order to be changed, but are we ever going to allow that?
if not then should we use fixed-clock for SOF clocks?

A virtual clock driver is added to SOF platform driver. Machine driver
could use the clock interface to send IPCs to SOF FW to enable/disable
the clocks.

Signed-off-by: Brent Lu <brent.lu@intel.com>
clkctrl.clk_en = enable ? 1 : 0;
clkctrl.clk_id = dai_clk->clk_id;

dev_dbg(sdev->dev, "clkctrl: SSP%d clk_en %d clk_id %d\n",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this clock SSP-only? If it is, it should be clear at the file / function level, if it isn't, it shouldn't be hard-coded here

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be better to be human readable:
dev_dbg(sdev->dev, "clkctrl: %s (clkid: %d) - %s\n", dai_clk->name, dai_clk->clk_id, enable ? "Enable" : "Disable");


init.name = pdata->dai_clks[i].name;
init.ops = &sof_clk_ops;
init.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_GATE;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not an expert in the clock API, but how about 0? :-) So far this clock doesn't even change rate, so why cannot it be cached?

}

dai_clk_lookup = clkdev_hw_create(&clkdev->hw, init.name,
NULL);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NULL would comfortably fit onto the previous line

do {
if (sdev->dai_clks_lookup[i])
clkdev_drop(sdev->dai_clks_lookup[i]);
} while (i-- > 0);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can simplify this: from your above code whenever on iteration i you encounter an error and jump to err you know, that all sdev->dai_clks_lookup[0..i-1] have been created successfully, right? So, you could just

while (i-- > 0)
	clkdev_drop(sdev->dai_clks_lookup[i]);

or similar

for (i = sdev->num_clks - 1; i >= 0; --i) {
if (sdev->dai_clks_lookup[i])
clkdev_drop(sdev->dai_clks_lookup[i]);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here: I assume, this is only called if .probe() above was successful. In that case you know, that all sdev->dai_clks_lookup[0..sdev->num_clks-1] elements have been created successfully

struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
int i;

for (i = sdev->num_clks - 1; i >= 0; --i) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just curious - any specific reason to run this in reverse order?

Comment thread include/sound/sof/dai.h
uint32_t dai_index; /**< index of this type dai */

uint32_t clk_en; /**< zero to disable the clock */
uint32_t clk_id; /**< clock id to operate */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how sure are we that this is all we'll ever need? Can it be that at some point we'll also need to send a rate down? Or maybe even the duty cycle (ok, maybe not this one)?

@brentlu
brentlu marked this pull request as draft May 20, 2021 09:28
@kv2019i
kv2019i requested a review from ujfalusi May 20, 2021 14:46
@ujfalusi

Copy link
Copy Markdown
Collaborator

I'm curious on how the clock API works on non DT world. How the machine driver would request the SCLK from one of the SSP ports the broken by design codec is connected to? Is it so that we just look for a unique clock name to request?
As a side note: it is not really the machine driver which should be handling the clock for the codec but the codec itself as it needs in order to be able to access registers. So whenever we want to write to the codec register we would need to clock (MCLK or/and SCLK) running.

struct sof_clk *clkdev;

clkdev = devm_kzalloc(dev, sizeof(*clkdev), GFP_KERNEL);
if (!clkdev) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this operations should be platform specific. In IMX case we just have the clocks defined in the device tree file (dts) and then just get a reference to the clock here.

Also, with the IMX we enable and configure IP clocks (not only DAI clocks) on the Host side.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dbaluta, you are right, but it should also depend on firmware version. Do we have the clock support enabled in the firmware?
At the end we will have SOF as a clock provider as well so platforms can move audio related clock implementations into the firmware and manage it via IPC.

@dbaluta dbaluta May 24, 2021 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ujfalusi for IMX there is little to zero support for IPs clocks in the firmware. 2 out of 3 IMX supported platforms have a dedicated M4 core that is running a firmware which handles the clocks.
I like the idea of making the SOF (DSP) as a clock provider. It will make sense for IMX future platforms.

@plbossart

Copy link
Copy Markdown
Member

@brentlu there is already an on-going work to start toggling the bclk during the hw_params stage and stop it during the hw_free stage. That would cover the current issues with most codecs and will be rather simple to backport.

I would like to push the introduction of new IPCs to a later stage when we have the SOF client support that @ujfalusi is working on.

@plbossart

Copy link
Copy Markdown
Member

let's work on #2965 for now, we'll have to add clock control when we have the SOF client in place.

@plbossart plbossart closed this Jun 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Explicit clock control

5 participants