Skip to content

Commit 8fede7f

Browse files
Icenowypdp7
authored andcommitted
clk: thead: support changing DPU pixel clock rate
The DPU pixel clock rate corresponds to the required dot clock of the display mode, so it needs to be tweakable. Add support to change it, by adding generic divider setting code, arming the code to the dpu0/dpu1 clocks, and setting the pixel clock connected to the DPU (after a gate) to CLK_SET_RATE_PARENT to propagate it to the dividers. Signed-off-by: Icenowy Zheng <uwu@icenowy.me> Reviewed-by: Drew Fustini <fustini@kernel.org> Signed-off-by: Drew Fustini <fustini@kernel.org>
1 parent 56a48c1 commit 8fede7f

1 file changed

Lines changed: 58 additions & 5 deletions

File tree

drivers/clk/thead/clk-th1520-ap.c

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct ccu_gate {
5656

5757
struct ccu_div {
5858
u32 enable;
59+
u32 div_en;
5960
struct ccu_div_internal div;
6061
struct ccu_internal mux;
6162
struct ccu_common common;
@@ -192,6 +193,55 @@ static unsigned long ccu_div_recalc_rate(struct clk_hw *hw,
192193
return rate;
193194
}
194195

196+
static int ccu_div_determine_rate(struct clk_hw *hw,
197+
struct clk_rate_request *req)
198+
{
199+
struct ccu_div *cd = hw_to_ccu_div(hw);
200+
unsigned int val;
201+
202+
if (cd->div_en)
203+
return divider_determine_rate(hw, req, NULL,
204+
cd->div.width, cd->div.flags);
205+
206+
regmap_read(cd->common.map, cd->common.cfg0, &val);
207+
val = val >> cd->div.shift;
208+
val &= GENMASK(cd->div.width - 1, 0);
209+
return divider_ro_determine_rate(hw, req, NULL, cd->div.width,
210+
cd->div.flags, val);
211+
}
212+
213+
static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate,
214+
unsigned long parent_rate)
215+
{
216+
struct ccu_div *cd = hw_to_ccu_div(hw);
217+
int val = divider_get_val(rate, parent_rate, NULL,
218+
cd->div.width, cd->div.flags);
219+
unsigned int curr_val, reg_val;
220+
221+
if (val < 0)
222+
return val;
223+
224+
regmap_read(cd->common.map, cd->common.cfg0, &reg_val);
225+
curr_val = reg_val >> cd->div.shift;
226+
curr_val &= GENMASK(cd->div.width - 1, 0);
227+
228+
if (!cd->div_en && curr_val != val)
229+
return -EINVAL;
230+
231+
reg_val &= ~cd->div_en;
232+
regmap_write(cd->common.map, cd->common.cfg0, reg_val);
233+
udelay(1);
234+
235+
reg_val &= ~GENMASK(cd->div.width + cd->div.shift - 1, cd->div.shift);
236+
reg_val |= val << cd->div.shift;
237+
regmap_write(cd->common.map, cd->common.cfg0, reg_val);
238+
239+
reg_val |= cd->div_en;
240+
regmap_write(cd->common.map, cd->common.cfg0, reg_val);
241+
242+
return 0;
243+
}
244+
195245
static u8 ccu_div_get_parent(struct clk_hw *hw)
196246
{
197247
struct ccu_div *cd = hw_to_ccu_div(hw);
@@ -234,7 +284,8 @@ static const struct clk_ops ccu_div_ops = {
234284
.get_parent = ccu_div_get_parent,
235285
.set_parent = ccu_div_set_parent,
236286
.recalc_rate = ccu_div_recalc_rate,
237-
.determine_rate = clk_hw_determine_rate_no_reparent,
287+
.set_rate = ccu_div_set_rate,
288+
.determine_rate = ccu_div_determine_rate,
238289
};
239290

240291
static void ccu_pll_disable(struct clk_hw *hw)
@@ -778,14 +829,15 @@ static struct ccu_div venc_clk = {
778829
};
779830

780831
static struct ccu_div dpu0_clk = {
832+
.div_en = BIT(8),
781833
.div = TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED),
782834
.common = {
783835
.clkid = CLK_DPU0,
784836
.cfg0 = 0x1e8,
785837
.hw.init = CLK_HW_INIT_PARENTS_HW("dpu0",
786838
dpu0_pll_clk_parent,
787839
&ccu_div_ops,
788-
0),
840+
CLK_SET_RATE_UNGATE),
789841
},
790842
};
791843

@@ -794,14 +846,15 @@ static const struct clk_parent_data dpu0_clk_pd[] = {
794846
};
795847

796848
static struct ccu_div dpu1_clk = {
849+
.div_en = BIT(8),
797850
.div = TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED),
798851
.common = {
799852
.clkid = CLK_DPU1,
800853
.cfg0 = 0x1ec,
801854
.hw.init = CLK_HW_INIT_PARENTS_HW("dpu1",
802855
dpu1_pll_clk_parent,
803856
&ccu_div_ops,
804-
0),
857+
CLK_SET_RATE_UNGATE),
805858
},
806859
};
807860

@@ -889,9 +942,9 @@ static CCU_GATE(CLK_GPU_CORE, gpu_core_clk, "gpu-core-clk", video_pll_clk_pd,
889942
static CCU_GATE(CLK_GPU_CFG_ACLK, gpu_cfg_aclk, "gpu-cfg-aclk",
890943
video_pll_clk_pd, 0x0, 4, 0);
891944
static CCU_GATE(CLK_DPU_PIXELCLK0, dpu0_pixelclk, "dpu0-pixelclk",
892-
dpu0_clk_pd, 0x0, 5, 0);
945+
dpu0_clk_pd, 0x0, 5, CLK_SET_RATE_PARENT);
893946
static CCU_GATE(CLK_DPU_PIXELCLK1, dpu1_pixelclk, "dpu1-pixelclk",
894-
dpu1_clk_pd, 0x0, 6, 0);
947+
dpu1_clk_pd, 0x0, 6, CLK_SET_RATE_PARENT);
895948
static CCU_GATE(CLK_DPU_HCLK, dpu_hclk, "dpu-hclk", video_pll_clk_pd, 0x0,
896949
7, 0);
897950
static CCU_GATE(CLK_DPU_ACLK, dpu_aclk, "dpu-aclk", video_pll_clk_pd, 0x0,

0 commit comments

Comments
 (0)