1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2023 Loongson Technology Corporation Limited
4 */
5
6 #include <linux/delay.h>
7
8 #include <drm/drm_managed.h>
9
10 #include "lsdc_drv.h"
11
12 /*
13 * The structure of the pixel PLL registers is evolved with times,
14 * it can be different across different chip also.
15 */
16
17 /* size is u64, note that all loongson's cpu is little endian.
18 * This structure is same for ls7a2000, ls7a1000 and ls2k2000.
19 */
20 struct lsdc_pixpll_reg {
21 /* Byte 0 ~ Byte 3 */
22 unsigned div_out : 7; /* 6 : 0 Output clock divider */
23 unsigned _reserved_1_ : 14; /* 20 : 7 */
24 unsigned loopc : 9; /* 29 : 21 Clock multiplier */
25 unsigned _reserved_2_ : 2; /* 31 : 30 */
26
27 /* Byte 4 ~ Byte 7 */
28 unsigned div_ref : 7; /* 38 : 32 Input clock divider */
29 unsigned locked : 1; /* 39 PLL locked indicator */
30 unsigned sel_out : 1; /* 40 output clk selector */
31 unsigned _reserved_3_ : 2; /* 42 : 41 */
32 unsigned set_param : 1; /* 43 Trigger the update */
33 unsigned bypass : 1; /* 44 */
34 unsigned powerdown : 1; /* 45 */
35 unsigned _reserved_4_ : 18; /* 46 : 63 no use */
36 };
37
38 union lsdc_pixpll_reg_bitmap {
39 struct lsdc_pixpll_reg bitmap;
40 u32 w[2];
41 u64 d;
42 };
43
44 struct clk_to_pixpll_parms_lookup_t {
45 unsigned int clock; /* kHz */
46
47 unsigned short width;
48 unsigned short height;
49 unsigned short vrefresh;
50
51 /* Stores parameters for programming the Hardware PLLs */
52 unsigned short div_out;
53 unsigned short loopc;
54 unsigned short div_ref;
55 };
56
57 static const struct clk_to_pixpll_parms_lookup_t pixpll_parms_table[] = {
58 {148500, 1920, 1080, 60, 11, 49, 3}, /* 1920x1080@60Hz */
59 {141750, 1920, 1080, 60, 11, 78, 5}, /* 1920x1080@60Hz */
60 /* 1920x1080@50Hz */
61 {174500, 1920, 1080, 75, 17, 89, 3}, /* 1920x1080@75Hz */
62 {181250, 2560, 1080, 75, 8, 58, 4}, /* 2560x1080@75Hz */
63 {297000, 2560, 1080, 30, 8, 95, 4}, /* 3840x2160@30Hz */
64 {301992, 1920, 1080, 100, 10, 151, 5}, /* 1920x1080@100Hz */
65 {146250, 1680, 1050, 60, 16, 117, 5}, /* 1680x1050@60Hz */
66 {135000, 1280, 1024, 75, 10, 54, 4}, /* 1280x1024@75Hz */
67 {119000, 1680, 1050, 60, 20, 119, 5}, /* 1680x1050@60Hz */
68 {108000, 1600, 900, 60, 15, 81, 5}, /* 1600x900@60Hz */
69 /* 1280x1024@60Hz */
70 /* 1280x960@60Hz */
71 /* 1152x864@75Hz */
72
73 {106500, 1440, 900, 60, 19, 81, 4}, /* 1440x900@60Hz */
74 {88750, 1440, 900, 60, 16, 71, 5}, /* 1440x900@60Hz */
75 {83500, 1280, 800, 60, 17, 71, 5}, /* 1280x800@60Hz */
76 {71000, 1280, 800, 60, 20, 71, 5}, /* 1280x800@60Hz */
77
78 {74250, 1280, 720, 60, 22, 49, 3}, /* 1280x720@60Hz */
79 /* 1280x720@50Hz */
80
81 {78750, 1024, 768, 75, 16, 63, 5}, /* 1024x768@75Hz */
82 {75000, 1024, 768, 70, 29, 87, 4}, /* 1024x768@70Hz */
83 {65000, 1024, 768, 60, 20, 39, 3}, /* 1024x768@60Hz */
84
85 {51200, 1024, 600, 60, 25, 64, 5}, /* 1024x600@60Hz */
86
87 {57284, 832, 624, 75, 24, 55, 4}, /* 832x624@75Hz */
88 {49500, 800, 600, 75, 40, 99, 5}, /* 800x600@75Hz */
89 {50000, 800, 600, 72, 44, 88, 4}, /* 800x600@72Hz */
90 {40000, 800, 600, 60, 30, 36, 3}, /* 800x600@60Hz */
91 {36000, 800, 600, 56, 50, 72, 4}, /* 800x600@56Hz */
92 {31500, 640, 480, 75, 40, 63, 5}, /* 640x480@75Hz */
93 /* 640x480@73Hz */
94
95 {30240, 640, 480, 67, 62, 75, 4}, /* 640x480@67Hz */
96 {27000, 720, 576, 50, 50, 54, 4}, /* 720x576@60Hz */
97 {25175, 640, 480, 60, 85, 107, 5}, /* 640x480@60Hz */
98 {25200, 640, 480, 60, 50, 63, 5}, /* 640x480@60Hz */
99 /* 720x480@60Hz */
100 };
101
lsdc_pixel_pll_free(struct drm_device * ddev,void * data)102 static void lsdc_pixel_pll_free(struct drm_device *ddev, void *data)
103 {
104 struct lsdc_pixpll *this = (struct lsdc_pixpll *)data;
105
106 iounmap(this->mmio);
107
108 kfree(this->priv);
109
110 drm_dbg(ddev, "pixpll private data freed\n");
111 }
112
113 /*
114 * ioremap the device dependent PLL registers
115 *
116 * @this: point to the object where this function is called from
117 */
lsdc_pixel_pll_setup(struct lsdc_pixpll * const this)118 static int lsdc_pixel_pll_setup(struct lsdc_pixpll * const this)
119 {
120 struct lsdc_pixpll_parms *pparms;
121
122 this->mmio = ioremap(this->reg_base, this->reg_size);
123 if (IS_ERR_OR_NULL(this->mmio))
124 return -ENOMEM;
125
126 pparms = kzalloc(sizeof(*pparms), GFP_KERNEL);
127 if (IS_ERR_OR_NULL(pparms))
128 return -ENOMEM;
129
130 pparms->ref_clock = LSDC_PLL_REF_CLK_KHZ;
131
132 this->priv = pparms;
133
134 return drmm_add_action_or_reset(this->ddev, lsdc_pixel_pll_free, this);
135 }
136
137 /*
138 * Find a set of pll parameters from a static local table which avoid
139 * computing the pll parameter eachtime a modeset is triggered.
140 *
141 * @this: point to the object where this function is called from
142 * @clock: the desired output pixel clock, the unit is kHz
143 * @pout: point to where the parameters to store if found
144 *
145 * Return 0 if success, return -1 if not found.
146 */
lsdc_pixpll_find(struct lsdc_pixpll * const this,unsigned int clock,struct lsdc_pixpll_parms * pout)147 static int lsdc_pixpll_find(struct lsdc_pixpll * const this,
148 unsigned int clock,
149 struct lsdc_pixpll_parms *pout)
150 {
151 unsigned int num = ARRAY_SIZE(pixpll_parms_table);
152 const struct clk_to_pixpll_parms_lookup_t *pt;
153 unsigned int i;
154
155 for (i = 0; i < num; ++i) {
156 pt = &pixpll_parms_table[i];
157
158 if (clock == pt->clock) {
159 pout->div_ref = pt->div_ref;
160 pout->loopc = pt->loopc;
161 pout->div_out = pt->div_out;
162
163 return 0;
164 }
165 }
166
167 drm_dbg_kms(this->ddev, "pixel clock %u: miss\n", clock);
168
169 return -1;
170 }
171
172 /*
173 * Find a set of pll parameters which have minimal difference with the
174 * desired pixel clock frequency. It does that by computing all of the
175 * possible combination. Compute the diff and find the combination with
176 * minimal diff.
177 *
178 * clock_out = refclk / div_ref * loopc / div_out
179 *
180 * refclk is determined by the oscillator mounted on motherboard(100MHz
181 * in almost all board)
182 *
183 * @this: point to the object from where this function is called
184 * @clock: the desired output pixel clock, the unit is kHz
185 * @pout: point to the out struct of lsdc_pixpll_parms
186 *
187 * Return 0 if a set of parameter is found, otherwise return the error
188 * between clock_kHz we wanted and the most closest candidate with it.
189 */
lsdc_pixel_pll_compute(struct lsdc_pixpll * const this,unsigned int clock,struct lsdc_pixpll_parms * pout)190 static int lsdc_pixel_pll_compute(struct lsdc_pixpll * const this,
191 unsigned int clock,
192 struct lsdc_pixpll_parms *pout)
193 {
194 struct lsdc_pixpll_parms *pparms = this->priv;
195 unsigned int refclk = pparms->ref_clock;
196 const unsigned int tolerance = 1000;
197 unsigned int min = tolerance;
198 unsigned int div_out, loopc, div_ref;
199 unsigned int computed;
200
201 if (!lsdc_pixpll_find(this, clock, pout))
202 return 0;
203
204 for (div_out = 6; div_out < 64; div_out++) {
205 for (div_ref = 3; div_ref < 6; div_ref++) {
206 for (loopc = 6; loopc < 161; loopc++) {
207 unsigned int diff = 0;
208
209 if (loopc < 12 * div_ref)
210 continue;
211 if (loopc > 32 * div_ref)
212 continue;
213
214 computed = refclk / div_ref * loopc / div_out;
215
216 if (clock >= computed)
217 diff = clock - computed;
218 else
219 diff = computed - clock;
220
221 if (diff < min) {
222 min = diff;
223 pparms->div_ref = div_ref;
224 pparms->div_out = div_out;
225 pparms->loopc = loopc;
226
227 if (diff == 0) {
228 *pout = *pparms;
229 return 0;
230 }
231 }
232 }
233 }
234 }
235
236 /* still acceptable */
237 if (min < tolerance) {
238 *pout = *pparms;
239 return 0;
240 }
241
242 drm_dbg(this->ddev, "can't find suitable params for %u khz\n", clock);
243
244 return min;
245 }
246
247 /* Pixel pll hardware related ops, per display pipe */
248
__pixpll_rreg(struct lsdc_pixpll * this,union lsdc_pixpll_reg_bitmap * dst)249 static void __pixpll_rreg(struct lsdc_pixpll *this,
250 union lsdc_pixpll_reg_bitmap *dst)
251 {
252 #if defined(CONFIG_64BIT)
253 dst->d = readq(this->mmio);
254 #else
255 dst->w[0] = readl(this->mmio);
256 dst->w[1] = readl(this->mmio + 4);
257 #endif
258 }
259
__pixpll_wreg(struct lsdc_pixpll * this,union lsdc_pixpll_reg_bitmap * src)260 static void __pixpll_wreg(struct lsdc_pixpll *this,
261 union lsdc_pixpll_reg_bitmap *src)
262 {
263 #if defined(CONFIG_64BIT)
264 writeq(src->d, this->mmio);
265 #else
266 writel(src->w[0], this->mmio);
267 writel(src->w[1], this->mmio + 4);
268 #endif
269 }
270
__pixpll_ops_powerup(struct lsdc_pixpll * const this)271 static void __pixpll_ops_powerup(struct lsdc_pixpll * const this)
272 {
273 union lsdc_pixpll_reg_bitmap pixpll_reg;
274
275 __pixpll_rreg(this, &pixpll_reg);
276
277 pixpll_reg.bitmap.powerdown = 0;
278
279 __pixpll_wreg(this, &pixpll_reg);
280 }
281
__pixpll_ops_powerdown(struct lsdc_pixpll * const this)282 static void __pixpll_ops_powerdown(struct lsdc_pixpll * const this)
283 {
284 union lsdc_pixpll_reg_bitmap pixpll_reg;
285
286 __pixpll_rreg(this, &pixpll_reg);
287
288 pixpll_reg.bitmap.powerdown = 1;
289
290 __pixpll_wreg(this, &pixpll_reg);
291 }
292
__pixpll_ops_on(struct lsdc_pixpll * const this)293 static void __pixpll_ops_on(struct lsdc_pixpll * const this)
294 {
295 union lsdc_pixpll_reg_bitmap pixpll_reg;
296
297 __pixpll_rreg(this, &pixpll_reg);
298
299 pixpll_reg.bitmap.sel_out = 1;
300
301 __pixpll_wreg(this, &pixpll_reg);
302 }
303
__pixpll_ops_off(struct lsdc_pixpll * const this)304 static void __pixpll_ops_off(struct lsdc_pixpll * const this)
305 {
306 union lsdc_pixpll_reg_bitmap pixpll_reg;
307
308 __pixpll_rreg(this, &pixpll_reg);
309
310 pixpll_reg.bitmap.sel_out = 0;
311
312 __pixpll_wreg(this, &pixpll_reg);
313 }
314
__pixpll_ops_bypass(struct lsdc_pixpll * const this)315 static void __pixpll_ops_bypass(struct lsdc_pixpll * const this)
316 {
317 union lsdc_pixpll_reg_bitmap pixpll_reg;
318
319 __pixpll_rreg(this, &pixpll_reg);
320
321 pixpll_reg.bitmap.bypass = 1;
322
323 __pixpll_wreg(this, &pixpll_reg);
324 }
325
__pixpll_ops_unbypass(struct lsdc_pixpll * const this)326 static void __pixpll_ops_unbypass(struct lsdc_pixpll * const this)
327 {
328 union lsdc_pixpll_reg_bitmap pixpll_reg;
329
330 __pixpll_rreg(this, &pixpll_reg);
331
332 pixpll_reg.bitmap.bypass = 0;
333
334 __pixpll_wreg(this, &pixpll_reg);
335 }
336
__pixpll_ops_untoggle_param(struct lsdc_pixpll * const this)337 static void __pixpll_ops_untoggle_param(struct lsdc_pixpll * const this)
338 {
339 union lsdc_pixpll_reg_bitmap pixpll_reg;
340
341 __pixpll_rreg(this, &pixpll_reg);
342
343 pixpll_reg.bitmap.set_param = 0;
344
345 __pixpll_wreg(this, &pixpll_reg);
346 }
347
__pixpll_ops_set_param(struct lsdc_pixpll * const this,struct lsdc_pixpll_parms const * p)348 static void __pixpll_ops_set_param(struct lsdc_pixpll * const this,
349 struct lsdc_pixpll_parms const *p)
350 {
351 union lsdc_pixpll_reg_bitmap pixpll_reg;
352
353 __pixpll_rreg(this, &pixpll_reg);
354
355 pixpll_reg.bitmap.div_ref = p->div_ref;
356 pixpll_reg.bitmap.loopc = p->loopc;
357 pixpll_reg.bitmap.div_out = p->div_out;
358
359 __pixpll_wreg(this, &pixpll_reg);
360 }
361
__pixpll_ops_toggle_param(struct lsdc_pixpll * const this)362 static void __pixpll_ops_toggle_param(struct lsdc_pixpll * const this)
363 {
364 union lsdc_pixpll_reg_bitmap pixpll_reg;
365
366 __pixpll_rreg(this, &pixpll_reg);
367
368 pixpll_reg.bitmap.set_param = 1;
369
370 __pixpll_wreg(this, &pixpll_reg);
371 }
372
__pixpll_ops_wait_locked(struct lsdc_pixpll * const this)373 static void __pixpll_ops_wait_locked(struct lsdc_pixpll * const this)
374 {
375 union lsdc_pixpll_reg_bitmap pixpll_reg;
376 unsigned int counter = 0;
377
378 do {
379 __pixpll_rreg(this, &pixpll_reg);
380
381 if (pixpll_reg.bitmap.locked)
382 break;
383
384 ++counter;
385 } while (counter < 2000);
386
387 drm_dbg(this->ddev, "%u loop waited\n", counter);
388 }
389
390 /*
391 * Update the PLL parameters to the PLL hardware
392 *
393 * @this: point to the object from which this function is called
394 * @pin: point to the struct of lsdc_pixpll_parms passed in
395 *
396 * return 0 if successful.
397 */
lsdc_pixpll_update(struct lsdc_pixpll * const this,struct lsdc_pixpll_parms const * pin)398 static int lsdc_pixpll_update(struct lsdc_pixpll * const this,
399 struct lsdc_pixpll_parms const *pin)
400 {
401 __pixpll_ops_bypass(this);
402
403 __pixpll_ops_off(this);
404
405 __pixpll_ops_powerdown(this);
406
407 __pixpll_ops_toggle_param(this);
408
409 __pixpll_ops_set_param(this, pin);
410
411 __pixpll_ops_untoggle_param(this);
412
413 __pixpll_ops_powerup(this);
414
415 udelay(2);
416
417 __pixpll_ops_wait_locked(this);
418
419 __pixpll_ops_on(this);
420
421 __pixpll_ops_unbypass(this);
422
423 return 0;
424 }
425
lsdc_pixpll_get_freq(struct lsdc_pixpll * const this)426 static unsigned int lsdc_pixpll_get_freq(struct lsdc_pixpll * const this)
427 {
428 struct lsdc_pixpll_parms *ppar = this->priv;
429 union lsdc_pixpll_reg_bitmap pix_pll_reg;
430 unsigned int freq;
431
432 __pixpll_rreg(this, &pix_pll_reg);
433
434 ppar->div_ref = pix_pll_reg.bitmap.div_ref;
435 ppar->loopc = pix_pll_reg.bitmap.loopc;
436 ppar->div_out = pix_pll_reg.bitmap.div_out;
437
438 freq = ppar->ref_clock / ppar->div_ref * ppar->loopc / ppar->div_out;
439
440 return freq;
441 }
442
lsdc_pixpll_print(struct lsdc_pixpll * const this,struct drm_printer * p)443 static void lsdc_pixpll_print(struct lsdc_pixpll * const this,
444 struct drm_printer *p)
445 {
446 struct lsdc_pixpll_parms *parms = this->priv;
447
448 drm_printf(p, "div_ref: %u, loopc: %u, div_out: %u\n",
449 parms->div_ref, parms->loopc, parms->div_out);
450 }
451
452 /*
453 * LS7A1000, LS7A2000 and ls2k2000's pixel pll setting register is same,
454 * we take this as default, create a new instance if a different model is
455 * introduced.
456 */
457 static const struct lsdc_pixpll_funcs __pixpll_default_funcs = {
458 .setup = lsdc_pixel_pll_setup,
459 .compute = lsdc_pixel_pll_compute,
460 .update = lsdc_pixpll_update,
461 .get_rate = lsdc_pixpll_get_freq,
462 .print = lsdc_pixpll_print,
463 };
464
465 /* pixel pll initialization */
466
lsdc_pixpll_init(struct lsdc_pixpll * const this,struct drm_device * ddev,unsigned int index)467 int lsdc_pixpll_init(struct lsdc_pixpll * const this,
468 struct drm_device *ddev,
469 unsigned int index)
470 {
471 struct lsdc_device *ldev = to_lsdc(ddev);
472 const struct lsdc_desc *descp = ldev->descp;
473 const struct loongson_gfx_desc *gfx = to_loongson_gfx(descp);
474
475 this->ddev = ddev;
476 this->reg_size = 8;
477 this->reg_base = gfx->conf_reg_base + gfx->pixpll[index].reg_offset;
478 this->funcs = &__pixpll_default_funcs;
479
480 return this->funcs->setup(this);
481 }
482