-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
unicam clock changes #3609
unicam clock changes #3609
Conversation
I'm not wild about the magic number 250 * 1000 * 1000 in the code as opposed to a macro constant, but it is only used once. Is it possible that this value might ever change? Should it be a DT parameter? I was going to raise some concerns about the SET_CLOCK_RATE mechanism, but I see that the firmware does the right thing and uses the "boost" mechanism, meaning that you won't reduce the clock if something else wants it to be higher. There appears to be no way to relinquish a claim on the clock minimum frequency, but is 0 a better minimum than 200MHz? My only remaining concern is over whether firmware-clocks needs a similar "boost" accounting mechanism as the firmware - what happens when one stream stops while the other is still going? What stops the core frequency from being reduced? |
Like the LP clock, this will (likely) never change. Having it as a DT parameter is reasonable, but perhaps overkill?
Dave and me discussed this very point, and we ended up setting it back to 200MHz like the HVS does.
Yes, this is a good point. I had actually assumed that firmware-clock already did this, will need to go look at the code in more detail. |
Max/min rates can be read from firmware, but I don't think the clock driver exposes that conveniently: Overlapping calls to control the same clock are not safe. Returning a cookie when boosting that is passed back in when unboosted is how the firmware deals with this but I don't know how that can be done though the clock interface. I don't know if something unique to the caller could be passed into the (extended) |
I did look at the max/min clock queries that can be done, but currently it's only there for PLLB (ARM clock). All the other clocks just get added. @mripard may be able to advise if there is a range check within the clock APIs, and confirm whether the clock framework deals with refcounting clock requests (I seem to recall him saying it does). |
I didn't add it since I wasn't aware of any use case for it before, but it's pretty trivial to add it if we need it.
Indeed it's only used for clipping at the moment and you can't retrieve it from the user API. It could be added I think if we have a use case for it. I'm not sure what the issue addressed in your patches is though. You need to have the VPU clock running at least at 250MHz while the unicam is running, and 200MHz otherwise?
The clock framework has some refcounting (on enable / disable for example), but not on all operations (set_rate doesn't for example). What kind of requests are we talking about here? |
The aim is address my question above:
The clock driver is a single client of the firmware but represents multiple clients within the kernel. Since the aim is to guarantee a minimum clock speed then something in either unicam or the clock driver needs to track how many streams are active and request the higher clock when the count is non-zero. My suggestion would be to add aliases of (at least) the core clock and get each of the unicam instances to use different aliases, allowing multiple uses to be tracked independently, unless you feel like making a more sweeping change. |
vc4 driver also boosts core clock during a mode set. I think that's the only other "official" user. User apps could also poke the mailbox directly. |
Those users should expect bad stuff to happen occasionally. |
Looks like:
if what's wanted rather than hardd coded numbers. |
Does that minimum clock speed change from one user to the other, or is it the same across all users? If it's the same rate for any user, then we could use the prepare / unprepare callbacks in the clock driver that are called any time a first / last user enables / disables the clock, and use them to raise it to the needed minimum rate, and back to the lower frequency once no-one enables it anymore. |
I expect it could be different per user. Unicam needs 250 MHz, where as HVS currently uses 500 MHz. |
In the HVS case, it's only when changing a mode, so it's not really the same thing than raising the clock when it starts to have a user? |
I don't think there's a way to get a satisfactory solution without looking at the clock rates requested at runtime from all users and calculating the maximum. |
Then I guess each user should call clk_set_min_rate with its requirement, and the clock framework will figure it out on its own between the hardware min and max (reported by the firmware in our case), and what has been set by each user. |
Is there really that extra level between the clock provider and the clock consumer? Do multiple callers to |
Yes, struct clk is only the customer facing side of the clock representation, and each user will have a different struct clk affected to it. The core uses the structs clk_core and clk_hw (clk_core for the generic parts, clk_hw is what's passed to the drivers) to represent each clocks. You can assign min and max rates on clk_core (to reflect boundaries of the hardware), or each user can do so on its struct clk (to reflect boundaries on what that particular user needs to be enforced). |
OK - found the per-caller struct clk allocation (with shared clk_hw), but clk_set_rate_range (the implementation of clk_set_min_rate) doesn't appear to share the limit changes, i.e. although applying a minimum might immediately change the clock rate, I don't see how it could prevent somebody else from changing it. Anyway, I'll let you worry about that. |
83784a1
to
971a2bb
Compare
So I took some time to confirm this this morning, and it's indeed pretty hard to see how it's occuring, but I believe it should work as expected. When calling clk_set_rate_range, if the current rate of the clock is outside of the range we want to enforce, it will call clk_core_set_rate_nolock to force the rate into the range: clk_set_rate_nolock will then call clk_core_req_round_rate_nolock on that new rate: And clk_core_req_round_rate_nolock will call clk_core_get_boundaries clk_core_get_boundaries is the function that will retrieve the range for all the users, and the clock provider, and will find the common range clk_core_req_round_rate_nolock will then call clk_core_round_rate_nolock using the new rate we want to enforce and the boundaries it discovered, but will not clamp it itself. It might be a bug there, but at least there's an attempt to do what we were discussing :) |
So with all of that, is the correct thing to do as follows:
? |
Sadly this does not work as expected. |
I believe it works for arm clock in cpufreq driver. |
I guess you can even simplify that by just doing something like
But yeah, like @popcornmix was mentionning, this was not properly reported to the CCF at the moment. I can send a PR for the additional fixes I sent to the firmware clocks on that last series if you want? |
@mripard a PR for upstream clock fixes would be welcome. |
I just did that PR here: |
964dedc
to
ec8bbdc
Compare
What's the status of this? |
I've made the changes, but still have not tested them. One for next week I'm afraid. |
@pelwell, after a rebase, I get a compile error on the dtsi:
I tried adding the following block to the end of the file (which is probably incorrect), but no luck:
My device tree knowledge is very limited, any idea what I should be doing go get firmware_clock recognised again? |
It was broken by @mripard's change "clk: rpi: Adjust DT binding to match upstream", and then not fixed by my followup "SQUASH: dts: Fix firmware clocks support" because nothing other than raspberrypi-cpufreq was using firmware_clocks, and raspberrypi-cpufreq isn't using on BCM2835. Try this patch: pelwell@ab0ef79 |
Building with pelwell/linux@ab0ef79 seems to go further. Will do a run-test shortly. @pelwell, shall I include that patch in this PR, or did you intend to merge that separately? |
I've merged it to rpi-5.4.y. |
When streaming with Unicam, the VPU must have a clock frequency of at least 250Mhz. Otherwise, the input fifos could overrun, causing image corruption. Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
I think this is doing the right thing now. |
Cool - that looks pretty simple. I guess we want to make the vc4 display code use the same mechanism (unrelated to this PR). |
Update the documentation to reflect the new "VPU" clock needed by the bcm2835-unicam driver. Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
kernel: vc4_hdmi: Support HBR audio See: raspberrypi/linux#3717 kernel: OV7251 overlay and defconfig See: raspberrypi/linux#3714 kernel: Imx290 & unicam v4l2-compliance fixes See: raspberrypi/linux#3712 kernel: Enhances the DAC+ driver to control the optional headphone amplifier See: raspberrypi/linux#3711 kernel: OV9281 driver and overlay See: raspberrypi/linux#3709 kernel: dtoverlays: Fixup imx219 and imx477 overlays due to parsing failures See: raspberrypi/linux#3706 kernel: FKMS: max refresh rate and blocking 1366x768 See: raspberrypi/linux#3704 kernel: Fix lockups and IRQ jitter on multicore RasPis See: raspberrypi/linux#3703 kernel: dts: Further simplify firmware clocks See: raspberrypi/linux#3609 kernel: configs: Add CAN_EMS_USB=m See: raspberrypi/linux#3716 kernel: configs: Enable CONFIG_BLK_DEV_NVME=m kernel: ARM: dts: Make bcm2711 dts more like 5.7 firmware: arm_loader: Don't enable the ARM USB IRQ See: raspberrypi/linux#3703 firmware: hdmi: Remove M2MC/BVB min turbo clock request
kernel: vc4_hdmi: Support HBR audio See: raspberrypi/linux#3717 kernel: OV7251 overlay and defconfig See: raspberrypi/linux#3714 kernel: Imx290 & unicam v4l2-compliance fixes See: raspberrypi/linux#3712 kernel: Enhances the DAC+ driver to control the optional headphone amplifier See: raspberrypi/linux#3711 kernel: OV9281 driver and overlay See: raspberrypi/linux#3709 kernel: dtoverlays: Fixup imx219 and imx477 overlays due to parsing failures See: raspberrypi/linux#3706 kernel: FKMS: max refresh rate and blocking 1366x768 See: raspberrypi/linux#3704 kernel: Fix lockups and IRQ jitter on multicore RasPis See: raspberrypi/linux#3703 kernel: dts: Further simplify firmware clocks See: raspberrypi/linux#3609 kernel: configs: Add CAN_EMS_USB=m See: raspberrypi/linux#3716 kernel: configs: Enable CONFIG_BLK_DEV_NVME=m kernel: ARM: dts: Make bcm2711 dts more like 5.7 firmware: arm_loader: Don't enable the ARM USB IRQ See: raspberrypi/linux#3703 firmware: hdmi: Remove M2MC/BVB min turbo clock request
It does in mainline already, @6by9 wanted to do a merge soon, so I guess it will come to 5.4 as well |
See: raspberrypi/linux#3730 kernel: drm/vc4: Add DRM_MODE_FLAG_DBLCLK support to vc4-fkms See: raspberrypi/linux#3725 kernel: raspberrypi: Report sensor orientation through DT See: raspberrypi/linux#3723 kernel: correct SND_SOC_DAILINK_DEFS See: raspberrypi/linux#3722 kernel: ARM: dts: Select the actpwr LED trigger on Zeroes kernel: staging: vc04_services: isp: Rework lens shading to take a dmabuf See: raspberrypi/linux#3715 kernel: unicam clock changes See: raspberrypi/linux#3609 firmware: IL: camera: Fix stereoscopic pool allocations firmware: arm_loader: Add support for double clock/pixel_rep for FKMS See: raspberrypi/linux#3725 firmware: scalerlib: Set the default chroma location for YUV10 to match 8bit firmware: scalerlib: Set chroma_vrep correctly for YUV10COL firmware: isp: check the hi-res resize filter mode when the input crop changes
See: raspberrypi/linux#3730 kernel: drm/vc4: Add DRM_MODE_FLAG_DBLCLK support to vc4-fkms See: raspberrypi/linux#3725 kernel: raspberrypi: Report sensor orientation through DT See: raspberrypi/linux#3723 kernel: correct SND_SOC_DAILINK_DEFS See: raspberrypi/linux#3722 kernel: ARM: dts: Select the actpwr LED trigger on Zeroes kernel: staging: vc04_services: isp: Rework lens shading to take a dmabuf See: raspberrypi/linux#3715 kernel: unicam clock changes See: raspberrypi/linux#3609 firmware: IL: camera: Fix stereoscopic pool allocations firmware: arm_loader: Add support for double clock/pixel_rep for FKMS See: raspberrypi/linux#3725 firmware: scalerlib: Set the default chroma location for YUV10 to match 8bit firmware: scalerlib: Set chroma_vrep correctly for YUV10COL firmware: isp: check the hi-res resize filter mode when the input crop changes
Add control of the vpu clock when streaming from unicam.