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 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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 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