mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 14:53:58 -04:00
Keep the convention of naming vlv_clock* instead of vlv_*_clock. Signed-off-by: Michał Grzelak <michal.grzelak@intel.com> Link: https://lore.kernel.org/r/20250919215413.1006296-1-michal.grzelak@intel.com Signed-off-by: Jani Nikula <jani.nikula@intel.com>
89 lines
2.4 KiB
C
89 lines
2.4 KiB
C
// SPDX-License-Identifier: MIT
|
|
/* Copyright © 2025 Intel Corporation */
|
|
|
|
#include <drm/drm_print.h>
|
|
|
|
#include "intel_display_core.h"
|
|
#include "intel_display_types.h"
|
|
#include "vlv_clock.h"
|
|
#include "vlv_sideband.h"
|
|
|
|
/*
|
|
* FIXME: The caching of hpll_freq and czclk_freq relies on the first calls
|
|
* occurring at a time when they can actually be read. This appears to be the
|
|
* case, but is somewhat fragile. Make the initialization explicit at a point
|
|
* where they can be reliably read.
|
|
*/
|
|
|
|
/* returns HPLL frequency in kHz */
|
|
int vlv_clock_get_hpll_vco(struct drm_device *drm)
|
|
{
|
|
struct intel_display *display = to_intel_display(drm);
|
|
int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
|
|
|
|
if (!display->vlv_clock.hpll_freq) {
|
|
vlv_cck_get(drm);
|
|
/* Obtain SKU information */
|
|
hpll_freq = vlv_cck_read(drm, CCK_FUSE_REG) &
|
|
CCK_FUSE_HPLL_FREQ_MASK;
|
|
vlv_cck_put(drm);
|
|
|
|
display->vlv_clock.hpll_freq = vco_freq[hpll_freq] * 1000;
|
|
|
|
drm_dbg_kms(drm, "HPLL frequency: %d kHz\n", display->vlv_clock.hpll_freq);
|
|
}
|
|
|
|
return display->vlv_clock.hpll_freq;
|
|
}
|
|
|
|
static int vlv_clock_get_cck(struct drm_device *drm,
|
|
const char *name, u32 reg, int ref_freq)
|
|
{
|
|
u32 val;
|
|
int divider;
|
|
|
|
vlv_cck_get(drm);
|
|
val = vlv_cck_read(drm, reg);
|
|
vlv_cck_put(drm);
|
|
|
|
divider = val & CCK_FREQUENCY_VALUES;
|
|
|
|
drm_WARN(drm, (val & CCK_FREQUENCY_STATUS) !=
|
|
(divider << CCK_FREQUENCY_STATUS_SHIFT),
|
|
"%s change in progress\n", name);
|
|
|
|
return DIV_ROUND_CLOSEST(ref_freq << 1, divider + 1);
|
|
}
|
|
|
|
int vlv_clock_get_hrawclk(struct drm_device *drm)
|
|
{
|
|
/* RAWCLK_FREQ_VLV register updated from power well code */
|
|
return vlv_clock_get_cck(drm, "hrawclk", CCK_DISPLAY_REF_CLOCK_CONTROL,
|
|
vlv_clock_get_hpll_vco(drm));
|
|
}
|
|
|
|
int vlv_clock_get_czclk(struct drm_device *drm)
|
|
{
|
|
struct intel_display *display = to_intel_display(drm);
|
|
|
|
if (!display->vlv_clock.czclk_freq) {
|
|
display->vlv_clock.czclk_freq = vlv_clock_get_cck(drm, "czclk", CCK_CZ_CLOCK_CONTROL,
|
|
vlv_clock_get_hpll_vco(drm));
|
|
drm_dbg_kms(drm, "CZ clock rate: %d kHz\n", display->vlv_clock.czclk_freq);
|
|
}
|
|
|
|
return display->vlv_clock.czclk_freq;
|
|
}
|
|
|
|
int vlv_clock_get_cdclk(struct drm_device *drm)
|
|
{
|
|
return vlv_clock_get_cck(drm, "cdclk", CCK_DISPLAY_CLOCK_CONTROL,
|
|
vlv_clock_get_hpll_vco(drm));
|
|
}
|
|
|
|
int vlv_clock_get_gpll(struct drm_device *drm)
|
|
{
|
|
return vlv_clock_get_cck(drm, "GPLL ref", CCK_GPLL_CLOCK_CONTROL,
|
|
vlv_clock_get_czclk(drm));
|
|
}
|