diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-06-29 21:00:17 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-06-29 21:00:17 +0300 |
commit | 1b722407a13b7f8658d2e26917791f32805980a2 (patch) | |
tree | 30aab582725a46e42843d75e2eb9ce4151f0f3ed /drivers/gpu/drm/sun4i/sun4i_tcon_dclk.c | |
parent | f8824e151fbfa0ac0a258015d606ea6f4a10251b (diff) | |
parent | 5ff2977b19769fd24b0cfbe7cbe4d5114b6106af (diff) | |
download | linux-1b722407a13b7f8658d2e26917791f32805980a2.tar.xz |
Merge tag 'drm-next-2023-06-29' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie:
"There is one set of patches to misc for a i915 gsc/mei proxy driver.
Otherwise it's mostly amdgpu/i915/msm, lots of hw enablement and lots
of refactoring.
core:
- replace strlcpy with strscpy
- EDID changes to support further conversion to struct drm_edid
- Move i915 DSC parameter code to common DRM helpers
- Add Colorspace functionality
aperture:
- ignore framebuffers with non-primary devices
fbdev:
- use fbdev i/o helpers
- add Kconfig options for fb_ops helpers
- use new fb io helpers directly in drivers
sysfs:
- export DRM connector ID
scheduler:
- Avoid an infinite loop
ttm:
- store function table in .rodata
- Add query for TTM mem limit
- Add NUMA awareness to pools
- Export ttm_pool_fini()
bridge:
- fsl-ldb: support i.MX6SX
- lt9211, lt9611: remove blanking packets
- tc358768: implement input bus formats, devm cleanups
- ti-snd65dsi86: implement wait_hpd_asserted
- analogix: fix endless probe loop
- samsung-dsim: support swapped clock, fix enabling, support var
clock
- display-connector: Add support for external power supply
- imx: Fix module linking
- tc358762: Support reset GPIO
panel:
- nt36523: Support Lenovo J606F
- st7703: Support Anbernic RG353V-V2
- InnoLux G070ACE-L01 support
- boe-tv101wum-nl6: Improve initialization
- sharp-ls043t1le001: Mode fixes
- simple: BOE EV121WXM-N10-1850, S6D7AA0
- Ampire AM-800480L1TMQW-T00H
- Rocktech RK043FN48H
- Starry himax83102-j02
- Starry ili9882t
amdgpu:
- add new ctx query flag to handle reset better
- add new query/set shadow buffer for rdna3
- DCN 3.2/3.1.x/3.0.x updates
- Enable DC_FP on loongarch
- PCIe fix for RDNA2
- improve DC FAMS/SubVP support for better power management
- partition support for lots of engines
- Take NUMA into account when allocating memory
- Add new DRM_AMDGPU_WERROR config parameter to help with CI
- Initial SMU13 overdrive support
- Add support for new colorspace KMS API
- W=1 fixes
amdkfd:
- Query TTM mem limit rather than hardcoding it
- GC 9.4.3 partition support
- Handle NUMA for partitions
- Add debugger interface for enabling gdb
- Add KFD event age tracking
radeon:
- Fix possible UAF
i915:
- new getparam for PXP support
- GSC/MEI proxy driver
- Meteorlake display enablement
- avoid clearing preallocated framebuffers with TTM
- implement framebuffer mmap support
- Disable sampler indirect state in bindless heap
- Enable fdinfo for GuC backends
- GuC loading and firmware table handling fixes
- Various refactors for multi-tile enablement
- Define MOCS and PAT tables for MTL
- GSC/MEI support for Meteorlake
- PMU multi-tile support
- Large driver kernel doc cleanup
- Allow VRR toggling and arbitrary refresh rates
- Support async flips on linear buffers on display ver 12+
- Expose CRTC CTM property on ILK/SNB/VLV
- New debugfs for display clock frequencies
- Hotplug refactoring
- Display refactoring
- I915_GEM_CREATE_EXT_SET_PAT for Mesa on Meteorlake
- Use large rings for compute contexts
- HuC loading for MTL
- Allow user to set cache at BO creation
- MTL powermanagement enhancements
- Switch to dedicated workqueues to stop using flush_scheduled_work()
- Move display runtime init under display/
- Remove 10bit gamma on desktop gen3 parts, they don't support it
habanalabs:
- uapi: return 0 for user queries if there was a h/w or f/w error
- Add pci health check when we lose connection with the firmware.
This can be used to distinguish between pci link down and firmware
getting stuck.
- Add more info to the error print when TPC interrupt occur.
- Firmware fixes
msm:
- Adreno A660 bindings
- SM8350 MDSS bindings fix
- Added support for DPU on sm6350 and sm6375 platforms
- Implemented tearcheck support to support vsync on SM150 and newer
platforms
- Enabled missing features (DSPP, DSC, split display) on sc8180x,
sc8280xp, sm8450
- Added support for DSI and 28nm DSI PHY on MSM8226 platform
- Added support for DSI on sm6350 and sm6375 platforms
- Added support for display controller on MSM8226 platform
- A690 GPU support
- Move cmdstream dumping out of fence signaling path
- a610 support
- Support for a6xx devices without GMU
nouveau:
- NULL ptr before deref fixes
armada:
- implement fbdev emulation as client
sun4i:
- fix mipi-dsi dotclock
- release clocks
vc4:
- rgb range toggle property
- BT601 / BT2020 HDMI support
vkms:
- convert to drmm helpers
- add reflection and rotation support
- fix rgb565 conversion
gma500:
- fix iomem access
shmobile:
- support renesas soc platform
- enable fbdev
mxsfb:
- Add support for i.MX93 LCDIF
stm:
- dsi: Use devm_ helper
- ltdc: Fix potential invalid pointer deref
renesas:
- Group drivers in renesas subdirectory to prepare for new platform
- Drop deprecated R-Car H3 ES1.x support
meson:
- Add support for MIPI DSI displays
virtio:
- add sync object support
mediatek:
- Add display binding document for MT6795"
* tag 'drm-next-2023-06-29' of git://anongit.freedesktop.org/drm/drm: (1791 commits)
drm/i915: Fix a NULL vs IS_ERR() bug
drm/i915: make i915_drm_client_fdinfo() reference conditional again
drm/i915/huc: Fix missing error code in intel_huc_init()
drm/i915/gsc: take a wakeref for the proxy-init-completion check
drm/msm/a6xx: Add A610 speedbin support
drm/msm/a6xx: Add A619_holi speedbin support
drm/msm/a6xx: Use adreno_is_aXYZ macros in speedbin matching
drm/msm/a6xx: Use "else if" in GPU speedbin rev matching
drm/msm/a6xx: Fix some A619 tunables
drm/msm/a6xx: Add A610 support
drm/msm/a6xx: Add support for A619_holi
drm/msm/adreno: Disable has_cached_coherent in GMU wrapper configurations
drm/msm/a6xx: Introduce GMU wrapper support
drm/msm/a6xx: Move CX GMU power counter enablement to hw_init
drm/msm/a6xx: Extend and explain UBWC config
drm/msm/a6xx: Remove both GBIF and RBBM GBIF halt on hw init
drm/msm/a6xx: Add a helper for software-resetting the GPU
drm/msm/a6xx: Improve a6xx_bus_clear_pending_transactions()
drm/msm/a6xx: Move a6xx_bus_clear_pending_transactions to a6xx_gpu
drm/msm/a6xx: Move force keepalive vote removal to a6xx_gmu_force_off()
...
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun4i_tcon_dclk.c')
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tcon_dclk.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon_dclk.c b/drivers/gpu/drm/sun4i/sun4i_tcon_dclk.c new file mode 100644 index 000000000000..03d7de1911cd --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun4i_tcon_dclk.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2016 Free Electrons + * Copyright (C) 2016 NextThing Co + * + * Maxime Ripard <maxime.ripard@free-electrons.com> + */ + +#include <linux/clk-provider.h> +#include <linux/regmap.h> + +#include "sun4i_tcon.h" +#include "sun4i_tcon_dclk.h" + +struct sun4i_dclk { + struct clk_hw hw; + struct regmap *regmap; + struct sun4i_tcon *tcon; +}; + +static inline struct sun4i_dclk *hw_to_dclk(struct clk_hw *hw) +{ + return container_of(hw, struct sun4i_dclk, hw); +} + +static void sun4i_dclk_disable(struct clk_hw *hw) +{ + struct sun4i_dclk *dclk = hw_to_dclk(hw); + + regmap_update_bits(dclk->regmap, SUN4I_TCON0_DCLK_REG, + BIT(SUN4I_TCON0_DCLK_GATE_BIT), 0); +} + +static int sun4i_dclk_enable(struct clk_hw *hw) +{ + struct sun4i_dclk *dclk = hw_to_dclk(hw); + + return regmap_update_bits(dclk->regmap, SUN4I_TCON0_DCLK_REG, + BIT(SUN4I_TCON0_DCLK_GATE_BIT), + BIT(SUN4I_TCON0_DCLK_GATE_BIT)); +} + +static int sun4i_dclk_is_enabled(struct clk_hw *hw) +{ + struct sun4i_dclk *dclk = hw_to_dclk(hw); + u32 val; + + regmap_read(dclk->regmap, SUN4I_TCON0_DCLK_REG, &val); + + return val & BIT(SUN4I_TCON0_DCLK_GATE_BIT); +} + +static unsigned long sun4i_dclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sun4i_dclk *dclk = hw_to_dclk(hw); + u32 val; + + regmap_read(dclk->regmap, SUN4I_TCON0_DCLK_REG, &val); + + val >>= SUN4I_TCON0_DCLK_DIV_SHIFT; + val &= (1 << SUN4I_TCON0_DCLK_DIV_WIDTH) - 1; + + if (!val) + val = 1; + + return parent_rate / val; +} + +static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct sun4i_dclk *dclk = hw_to_dclk(hw); + struct sun4i_tcon *tcon = dclk->tcon; + unsigned long best_parent = 0; + u8 best_div = 1; + int i; + + for (i = tcon->dclk_min_div; i <= tcon->dclk_max_div; i++) { + u64 ideal = (u64)rate * i; + unsigned long rounded; + + /* + * ideal has overflowed the max value that can be stored in an + * unsigned long, and every clk operation we might do on a + * truncated u64 value will give us incorrect results. + * Let's just stop there since bigger dividers will result in + * the same overflow issue. + */ + if (ideal > ULONG_MAX) + goto out; + + rounded = clk_hw_round_rate(clk_hw_get_parent(hw), + ideal); + + if (rounded == ideal) { + best_parent = rounded; + best_div = i; + goto out; + } + + if (abs(rate - rounded / i) < + abs(rate - best_parent / best_div)) { + best_parent = rounded; + best_div = i; + } + } + +out: + *parent_rate = best_parent; + + return best_parent / best_div; +} + +static int sun4i_dclk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct sun4i_dclk *dclk = hw_to_dclk(hw); + u8 div = parent_rate / rate; + + return regmap_update_bits(dclk->regmap, SUN4I_TCON0_DCLK_REG, + GENMASK(6, 0), div); +} + +static int sun4i_dclk_get_phase(struct clk_hw *hw) +{ + struct sun4i_dclk *dclk = hw_to_dclk(hw); + u32 val; + + regmap_read(dclk->regmap, SUN4I_TCON0_IO_POL_REG, &val); + + val >>= 28; + val &= 3; + + return val * 120; +} + +static int sun4i_dclk_set_phase(struct clk_hw *hw, int degrees) +{ + struct sun4i_dclk *dclk = hw_to_dclk(hw); + u32 val = degrees / 120; + + val <<= 28; + + regmap_update_bits(dclk->regmap, SUN4I_TCON0_IO_POL_REG, + GENMASK(29, 28), + val); + + return 0; +} + +static const struct clk_ops sun4i_dclk_ops = { + .disable = sun4i_dclk_disable, + .enable = sun4i_dclk_enable, + .is_enabled = sun4i_dclk_is_enabled, + + .recalc_rate = sun4i_dclk_recalc_rate, + .round_rate = sun4i_dclk_round_rate, + .set_rate = sun4i_dclk_set_rate, + + .get_phase = sun4i_dclk_get_phase, + .set_phase = sun4i_dclk_set_phase, +}; + +int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon) +{ + const char *clk_name, *parent_name; + struct clk_init_data init; + struct sun4i_dclk *dclk; + int ret; + + parent_name = __clk_get_name(tcon->sclk0); + ret = of_property_read_string_index(dev->of_node, + "clock-output-names", 0, + &clk_name); + if (ret) + return ret; + + dclk = devm_kzalloc(dev, sizeof(*dclk), GFP_KERNEL); + if (!dclk) + return -ENOMEM; + dclk->tcon = tcon; + + init.name = clk_name; + init.ops = &sun4i_dclk_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = CLK_SET_RATE_PARENT; + + dclk->regmap = tcon->regs; + dclk->hw.init = &init; + + tcon->dclk = clk_register(dev, &dclk->hw); + if (IS_ERR(tcon->dclk)) + return PTR_ERR(tcon->dclk); + + return 0; +} +EXPORT_SYMBOL(sun4i_dclk_create); + +int sun4i_dclk_free(struct sun4i_tcon *tcon) +{ + clk_unregister(tcon->dclk); + return 0; +} +EXPORT_SYMBOL(sun4i_dclk_free); |