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 (!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 */ 149 static 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 */ 192 static 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 251 static 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 262 static 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 273 static 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 284 static 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 295 static 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 306 static 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 317 static 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 328 static 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 339 static 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 350 static 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 364 static 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 375 static 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 */ 400 static 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 428 static 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 445 static 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 */ 459 static 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 469 int 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