Files
android_kernel_samsung_sm86…/msm/dsi/dsi_pll.h
Satya Rama Aditya Pinapala 0a93edbae6 disp: msm: dsi: rework DSI PLL to be configured within PHY
Change avoids clock framework APIs to configure the DSI PHY
PLL. It follows HW recommendation to set the byte and pclk
dividers.

Change-Id: I8c110f3997e4ec4c2eaa28778b70091855725ab8
Signed-off-by: Satya Rama Aditya Pinapala <psraditya30@codeaurora.org>
2021-01-12 23:49:11 -08:00

181 lines
3.9 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
*/
#ifndef __DSI_PLL_H
#define __DSI_PLL_H
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/regmap.h>
#include "clk-regmap.h"
#include "clk-regmap-divider.h"
#include "clk-regmap-mux.h"
#include "dsi_defs.h"
#define DSI_PLL_DBG(p, fmt, ...) DRM_DEV_DEBUG(NULL, "[msm-dsi-debug]: DSI_PLL_%d: "\
fmt, p ? p->index : -1, ##__VA_ARGS__)
#define DSI_PLL_ERR(p, fmt, ...) DRM_DEV_ERROR(NULL, "[msm-dsi-error]: DSI_PLL_%d: "\
fmt, p ? p->index : -1, ##__VA_ARGS__)
#define DSI_PLL_INFO(p, fmt, ...) DRM_DEV_INFO(NULL, "[msm-dsi-info]: DSI_PLL_%d: "\
fmt, p ? p->index : -1, ##__VA_ARGS__)
#define DSI_PLL_WARN(p, fmt, ...) DRM_WARN("[msm-dsi-warn]: DSI_PLL_%d: "\
fmt, p ? p->index : -1, ##__VA_ARGS__)
#define DSI_PLL_REG_W(base, offset, data) \
writel_relaxed((data), (base) + (offset))
#define DSI_PLL_REG_R(base, offset) readl_relaxed((base) + (offset))
#define PLL_CALC_DATA(addr0, addr1, data0, data1) \
(((data1) << 24) | ((((addr1) / 4) & 0xFF) << 16) | \
((data0) << 8) | (((addr0) / 4) & 0xFF))
#define DSI_DYN_PLL_REG_W(base, offset, addr0, addr1, data0, data1) \
writel_relaxed(PLL_CALC_DATA(addr0, addr1, data0, data1), \
(base) + (offset))
#define upper_8_bit(x) ((((x) >> 2) & 0x100) >> 8)
#define DFPS_MAX_NUM_OF_FRAME_RATES 16
#define MAX_DSI_PLL_EN_SEQS 10
/* Register offsets for 5nm PHY PLL */
#define MMSS_DSI_PHY_PLL_PLL_CNTRL (0x0014)
#define MMSS_DSI_PHY_PLL_PLL_BKG_KVCO_CAL_EN (0x002C)
#define MMSS_DSI_PHY_PLL_PLLLOCK_CMP_EN (0x009C)
struct lpfr_cfg {
unsigned long vco_rate;
u32 r;
};
enum {
DSI_PLL_5NM,
DSI_PLL_10NM,
DSI_UNKNOWN_PLL,
};
struct dfps_pll_codes {
uint32_t pll_codes_1;
uint32_t pll_codes_2;
uint32_t pll_codes_3;
};
struct dfps_codes_info {
uint32_t is_valid;
uint32_t clk_rate; /* hz */
struct dfps_pll_codes pll_codes;
};
struct dfps_info {
uint32_t vco_rate_cnt;
struct dfps_codes_info codes_dfps[DFPS_MAX_NUM_OF_FRAME_RATES];
};
struct dsi_pll_resource {
/*
* dsi base register, phy, gdsc and dynamic refresh
* register mapping
*/
void __iomem *pll_base;
void __iomem *phy_base;
void __iomem *gdsc_base;
void __iomem *dyn_pll_base;
s64 vco_current_rate;
s64 vco_ref_clk_rate;
s64 vco_min_rate;
s64 vco_rate;
s64 byteclk_rate;
s64 pclk_rate;
u32 pll_revision;
/* HW recommended delay during configuration of vco clock rate */
u32 vco_delay;
/*
* Certain plls' do not allow vco rate update if it is on. Keep track of
* status for them to turn on/off after set rate success.
*/
bool pll_on;
/*
* caching the pll trim codes in the case of dynamic refresh
*/
int cache_pll_trim_codes[3];
/*
* PLL index if multiple index are available. Eg. in case of
* DSI we have 2 plls.
*/
uint32_t index;
bool ssc_en; /* share pll with master */
bool ssc_center; /* default is down spread */
u32 ssc_freq;
u32 ssc_ppm;
struct dsi_pll_resource *slave;
void *priv;
/*
* dynamic refresh pll codes stored in this structure
*/
struct dfps_info *dfps;
/*
* DSI pixel depth and lane information
*/
int bpp;
int lanes;
/*
* DSI PHY type DPHY/CPHY
*/
enum dsi_phy_type type;
};
struct dsi_pll_clk {
struct clk_hw hw;
void *priv;
};
struct dsi_pll_vco_calc {
s32 div_frac_start1;
s32 div_frac_start2;
s32 div_frac_start3;
s64 dec_start1;
s64 dec_start2;
s64 pll_plllock_cmp1;
s64 pll_plllock_cmp2;
s64 pll_plllock_cmp3;
};
struct dsi_pll_div_table {
u32 min_hz;
u32 max_hz;
int pll_div;
int phy_div;
};
static inline struct dsi_pll_clk *to_pll_clk_hw(struct clk_hw *hw)
{
return container_of(hw, struct dsi_pll_clk, hw);
}
int dsi_pll_clock_register_5nm(struct platform_device *pdev,
struct dsi_pll_resource *pll_res);
int dsi_pll_init(struct platform_device *pdev,
struct dsi_pll_resource **pll_res);
#endif