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 */ 20struct 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 38union lsdc_pixpll_reg_bitmap { 39 struct lsdc_pixpll_reg bitmap; 40 u32 w[2]; 41 u64 d; 42}; 43 44struct 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 57static 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 102static 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 */ 118static 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 (!this->mmio) 124 return -ENOMEM; 125 126 pparms = kzalloc(sizeof(*pparms), GFP_KERNEL); 127 if (!pparms) { 128 iounmap(this->mmio); 129 return -ENOMEM; 130 } 131 132 pparms->ref_clock = LSDC_PLL_REF_CLK_KHZ; 133 134 this->priv = pparms; 135 136 return drmm_add_action_or_reset(this->ddev, lsdc_pixel_pll_free, this); 137} 138 139/* 140 * Find a set of pll parameters from a static local table which avoid 141 * computing the pll parameter eachtime a modeset is triggered. 142 * 143 * @this: point to the object where this function is called from 144 * @clock: the desired output pixel clock, the unit is kHz 145 * @pout: point to where the parameters to store if found 146 * 147 * Return 0 if success, return -1 if not found. 148 */ 149static int lsdc_pixpll_find(struct lsdc_pixpll * const this, 150 unsigned int clock, 151 struct lsdc_pixpll_parms *pout) 152{ 153 unsigned int num = ARRAY_SIZE(pixpll_parms_table); 154 const struct clk_to_pixpll_parms_lookup_t *pt; 155 unsigned int i; 156 157 for (i = 0; i < num; ++i) { 158 pt = &pixpll_parms_table[i]; 159 160 if (clock == pt->clock) { 161 pout->div_ref = pt->div_ref; 162 pout->loopc = pt->loopc; 163 pout->div_out = pt->div_out; 164 165 return 0; 166 } 167 } 168 169 drm_dbg_kms(this->ddev, "pixel clock %u: miss\n", clock); 170 171 return -1; 172} 173 174/* 175 * Find a set of pll parameters which have minimal difference with the 176 * desired pixel clock frequency. It does that by computing all of the 177 * possible combination. Compute the diff and find the combination with 178 * minimal diff. 179 * 180 * clock_out = refclk / div_ref * loopc / div_out 181 * 182 * refclk is determined by the oscillator mounted on motherboard(100MHz 183 * in almost all board) 184 * 185 * @this: point to the object from where this function is called 186 * @clock: the desired output pixel clock, the unit is kHz 187 * @pout: point to the out struct of lsdc_pixpll_parms 188 * 189 * Return 0 if a set of parameter is found, otherwise return the error 190 * between clock_kHz we wanted and the most closest candidate with it. 191 */ 192static int lsdc_pixel_pll_compute(struct lsdc_pixpll * const this, 193 unsigned int clock, 194 struct lsdc_pixpll_parms *pout) 195{ 196 struct lsdc_pixpll_parms *pparms = this->priv; 197 unsigned int refclk = pparms->ref_clock; 198 const unsigned int tolerance = 1000; 199 unsigned int min = tolerance; 200 unsigned int div_out, loopc, div_ref; 201 unsigned int computed; 202 203 if (!lsdc_pixpll_find(this, clock, pout)) 204 return 0; 205 206 for (div_out = 6; div_out < 64; div_out++) { 207 for (div_ref = 3; div_ref < 6; div_ref++) { 208 for (loopc = 6; loopc < 161; loopc++) { 209 unsigned int diff = 0; 210 211 if (loopc < 12 * div_ref) 212 continue; 213 if (loopc > 32 * div_ref) 214 continue; 215 216 computed = refclk / div_ref * loopc / div_out; 217 218 if (clock >= computed) 219 diff = clock - computed; 220 else 221 diff = computed - clock; 222 223 if (diff < min) { 224 min = diff; 225 pparms->div_ref = div_ref; 226 pparms->div_out = div_out; 227 pparms->loopc = loopc; 228 229 if (diff == 0) { 230 *pout = *pparms; 231 return 0; 232 } 233 } 234 } 235 } 236 } 237 238 /* still acceptable */ 239 if (min < tolerance) { 240 *pout = *pparms; 241 return 0; 242 } 243 244 drm_dbg(this->ddev, "can't find suitable params for %u khz\n", clock); 245 246 return min; 247} 248 249/* Pixel pll hardware related ops, per display pipe */ 250 251static void __pixpll_rreg(struct lsdc_pixpll *this, 252 union lsdc_pixpll_reg_bitmap *dst) 253{ 254#if defined(CONFIG_64BIT) 255 dst->d = readq(this->mmio); 256#else 257 dst->w[0] = readl(this->mmio); 258 dst->w[1] = readl(this->mmio + 4); 259#endif 260} 261 262static void __pixpll_wreg(struct lsdc_pixpll *this, 263 union lsdc_pixpll_reg_bitmap *src) 264{ 265#if defined(CONFIG_64BIT) 266 writeq(src->d, this->mmio); 267#else 268 writel(src->w[0], this->mmio); 269 writel(src->w[1], this->mmio + 4); 270#endif 271} 272 273static void __pixpll_ops_powerup(struct lsdc_pixpll * const this) 274{ 275 union lsdc_pixpll_reg_bitmap pixpll_reg; 276 277 __pixpll_rreg(this, &pixpll_reg); 278 279 pixpll_reg.bitmap.powerdown = 0; 280 281 __pixpll_wreg(this, &pixpll_reg); 282} 283 284static void __pixpll_ops_powerdown(struct lsdc_pixpll * const this) 285{ 286 union lsdc_pixpll_reg_bitmap pixpll_reg; 287 288 __pixpll_rreg(this, &pixpll_reg); 289 290 pixpll_reg.bitmap.powerdown = 1; 291 292 __pixpll_wreg(this, &pixpll_reg); 293} 294 295static void __pixpll_ops_on(struct lsdc_pixpll * const this) 296{ 297 union lsdc_pixpll_reg_bitmap pixpll_reg; 298 299 __pixpll_rreg(this, &pixpll_reg); 300 301 pixpll_reg.bitmap.sel_out = 1; 302 303 __pixpll_wreg(this, &pixpll_reg); 304} 305 306static void __pixpll_ops_off(struct lsdc_pixpll * const this) 307{ 308 union lsdc_pixpll_reg_bitmap pixpll_reg; 309 310 __pixpll_rreg(this, &pixpll_reg); 311 312 pixpll_reg.bitmap.sel_out = 0; 313 314 __pixpll_wreg(this, &pixpll_reg); 315} 316 317static void __pixpll_ops_bypass(struct lsdc_pixpll * const this) 318{ 319 union lsdc_pixpll_reg_bitmap pixpll_reg; 320 321 __pixpll_rreg(this, &pixpll_reg); 322 323 pixpll_reg.bitmap.bypass = 1; 324 325 __pixpll_wreg(this, &pixpll_reg); 326} 327 328static void __pixpll_ops_unbypass(struct lsdc_pixpll * const this) 329{ 330 union lsdc_pixpll_reg_bitmap pixpll_reg; 331 332 __pixpll_rreg(this, &pixpll_reg); 333 334 pixpll_reg.bitmap.bypass = 0; 335 336 __pixpll_wreg(this, &pixpll_reg); 337} 338 339static void __pixpll_ops_untoggle_param(struct lsdc_pixpll * const this) 340{ 341 union lsdc_pixpll_reg_bitmap pixpll_reg; 342 343 __pixpll_rreg(this, &pixpll_reg); 344 345 pixpll_reg.bitmap.set_param = 0; 346 347 __pixpll_wreg(this, &pixpll_reg); 348} 349 350static void __pixpll_ops_set_param(struct lsdc_pixpll * const this, 351 struct lsdc_pixpll_parms const *p) 352{ 353 union lsdc_pixpll_reg_bitmap pixpll_reg; 354 355 __pixpll_rreg(this, &pixpll_reg); 356 357 pixpll_reg.bitmap.div_ref = p->div_ref; 358 pixpll_reg.bitmap.loopc = p->loopc; 359 pixpll_reg.bitmap.div_out = p->div_out; 360 361 __pixpll_wreg(this, &pixpll_reg); 362} 363 364static void __pixpll_ops_toggle_param(struct lsdc_pixpll * const this) 365{ 366 union lsdc_pixpll_reg_bitmap pixpll_reg; 367 368 __pixpll_rreg(this, &pixpll_reg); 369 370 pixpll_reg.bitmap.set_param = 1; 371 372 __pixpll_wreg(this, &pixpll_reg); 373} 374 375static void __pixpll_ops_wait_locked(struct lsdc_pixpll * const this) 376{ 377 union lsdc_pixpll_reg_bitmap pixpll_reg; 378 unsigned int counter = 0; 379 380 do { 381 __pixpll_rreg(this, &pixpll_reg); 382 383 if (pixpll_reg.bitmap.locked) 384 break; 385 386 ++counter; 387 } while (counter < 2000); 388 389 drm_dbg(this->ddev, "%u loop waited\n", counter); 390} 391 392/* 393 * Update the PLL parameters to the PLL hardware 394 * 395 * @this: point to the object from which this function is called 396 * @pin: point to the struct of lsdc_pixpll_parms passed in 397 * 398 * return 0 if successful. 399 */ 400static int lsdc_pixpll_update(struct lsdc_pixpll * const this, 401 struct lsdc_pixpll_parms const *pin) 402{ 403 __pixpll_ops_bypass(this); 404 405 __pixpll_ops_off(this); 406 407 __pixpll_ops_powerdown(this); 408 409 __pixpll_ops_toggle_param(this); 410 411 __pixpll_ops_set_param(this, pin); 412 413 __pixpll_ops_untoggle_param(this); 414 415 __pixpll_ops_powerup(this); 416 417 udelay(2); 418 419 __pixpll_ops_wait_locked(this); 420 421 __pixpll_ops_on(this); 422 423 __pixpll_ops_unbypass(this); 424 425 return 0; 426} 427 428static unsigned int lsdc_pixpll_get_freq(struct lsdc_pixpll * const this) 429{ 430 struct lsdc_pixpll_parms *ppar = this->priv; 431 union lsdc_pixpll_reg_bitmap pix_pll_reg; 432 unsigned int freq; 433 434 __pixpll_rreg(this, &pix_pll_reg); 435 436 ppar->div_ref = pix_pll_reg.bitmap.div_ref; 437 ppar->loopc = pix_pll_reg.bitmap.loopc; 438 ppar->div_out = pix_pll_reg.bitmap.div_out; 439 440 freq = ppar->ref_clock / ppar->div_ref * ppar->loopc / ppar->div_out; 441 442 return freq; 443} 444 445static void lsdc_pixpll_print(struct lsdc_pixpll * const this, 446 struct drm_printer *p) 447{ 448 struct lsdc_pixpll_parms *parms = this->priv; 449 450 drm_printf(p, "div_ref: %u, loopc: %u, div_out: %u\n", 451 parms->div_ref, parms->loopc, parms->div_out); 452} 453 454/* 455 * LS7A1000, LS7A2000 and ls2k2000's pixel pll setting register is same, 456 * we take this as default, create a new instance if a different model is 457 * introduced. 458 */ 459static const struct lsdc_pixpll_funcs __pixpll_default_funcs = { 460 .setup = lsdc_pixel_pll_setup, 461 .compute = lsdc_pixel_pll_compute, 462 .update = lsdc_pixpll_update, 463 .get_rate = lsdc_pixpll_get_freq, 464 .print = lsdc_pixpll_print, 465}; 466 467/* pixel pll initialization */ 468 469int lsdc_pixpll_init(struct lsdc_pixpll * const this, 470 struct drm_device *ddev, 471 unsigned int index) 472{ 473 struct lsdc_device *ldev = to_lsdc(ddev); 474 const struct lsdc_desc *descp = ldev->descp; 475 const struct loongson_gfx_desc *gfx = to_loongson_gfx(descp); 476 477 this->ddev = ddev; 478 this->reg_size = 8; 479 this->reg_base = gfx->conf_reg_base + gfx->pixpll[index].reg_offset; 480 this->funcs = &__pixpll_default_funcs; 481 482 return this->funcs->setup(this); 483} 484