1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2014 Traphandler 4 * Copyright (C) 2014 Free Electrons 5 * 6 * Author: Jean-Jacques Hiblot <jjhiblot@traphandler.com> 7 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> 8 */ 9 10 #include <linux/clk.h> 11 #include <linux/mfd/atmel-hlcdc.h> 12 #include <linux/pinctrl/consumer.h> 13 #include <linux/pm.h> 14 #include <linux/pm_runtime.h> 15 16 #include <video/videomode.h> 17 18 #include <drm/drm_atomic.h> 19 #include <drm/drm_atomic_helper.h> 20 #include <drm/drm_crtc.h> 21 #include <drm/drm_modeset_helper_vtables.h> 22 #include <drm/drm_probe_helper.h> 23 #include <drm/drm_vblank.h> 24 25 #include "atmel_hlcdc_dc.h" 26 27 /** 28 * struct atmel_hlcdc_crtc_state - Atmel HLCDC CRTC state structure 29 * 30 * @base: base CRTC state 31 * @output_mode: RGBXXX output mode 32 */ 33 struct atmel_hlcdc_crtc_state { 34 struct drm_crtc_state base; 35 unsigned int output_mode; 36 }; 37 38 static inline struct atmel_hlcdc_crtc_state * 39 drm_crtc_state_to_atmel_hlcdc_crtc_state(struct drm_crtc_state *state) 40 { 41 return container_of(state, struct atmel_hlcdc_crtc_state, base); 42 } 43 44 /** 45 * struct atmel_hlcdc_crtc - Atmel HLCDC CRTC structure 46 * 47 * @base: base DRM CRTC structure 48 * @dc: pointer to the atmel_hlcdc structure provided by the MFD device 49 * @event: pointer to the current page flip event 50 * @id: CRTC id (returned by drm_crtc_index) 51 */ 52 struct atmel_hlcdc_crtc { 53 struct drm_crtc base; 54 struct atmel_hlcdc_dc *dc; 55 struct drm_pending_vblank_event *event; 56 int id; 57 }; 58 59 static inline struct atmel_hlcdc_crtc * 60 drm_crtc_to_atmel_hlcdc_crtc(struct drm_crtc *crtc) 61 { 62 return container_of(crtc, struct atmel_hlcdc_crtc, base); 63 } 64 65 static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c) 66 { 67 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 68 struct regmap *regmap = crtc->dc->hlcdc->regmap; 69 struct drm_display_mode *adj = &c->state->adjusted_mode; 70 struct atmel_hlcdc_crtc_state *state; 71 unsigned long mode_rate; 72 struct videomode vm; 73 unsigned long prate; 74 unsigned int mask = ATMEL_HLCDC_CLKDIV_MASK | ATMEL_HLCDC_CLKPOL; 75 unsigned int cfg = 0; 76 int div, ret; 77 78 ret = clk_prepare_enable(crtc->dc->hlcdc->sys_clk); 79 if (ret) 80 return; 81 82 vm.vfront_porch = adj->crtc_vsync_start - adj->crtc_vdisplay; 83 vm.vback_porch = adj->crtc_vtotal - adj->crtc_vsync_end; 84 vm.vsync_len = adj->crtc_vsync_end - adj->crtc_vsync_start; 85 vm.hfront_porch = adj->crtc_hsync_start - adj->crtc_hdisplay; 86 vm.hback_porch = adj->crtc_htotal - adj->crtc_hsync_end; 87 vm.hsync_len = adj->crtc_hsync_end - adj->crtc_hsync_start; 88 89 regmap_write(regmap, ATMEL_HLCDC_CFG(1), 90 (vm.hsync_len - 1) | ((vm.vsync_len - 1) << 16)); 91 92 regmap_write(regmap, ATMEL_HLCDC_CFG(2), 93 (vm.vfront_porch - 1) | (vm.vback_porch << 16)); 94 95 regmap_write(regmap, ATMEL_HLCDC_CFG(3), 96 (vm.hfront_porch - 1) | ((vm.hback_porch - 1) << 16)); 97 98 regmap_write(regmap, ATMEL_HLCDC_CFG(4), 99 (adj->crtc_hdisplay - 1) | 100 ((adj->crtc_vdisplay - 1) << 16)); 101 102 prate = clk_get_rate(crtc->dc->hlcdc->sys_clk); 103 mode_rate = adj->crtc_clock * 1000; 104 if (!crtc->dc->desc->fixed_clksrc) { 105 prate *= 2; 106 cfg |= ATMEL_HLCDC_CLKSEL; 107 mask |= ATMEL_HLCDC_CLKSEL; 108 } 109 110 div = DIV_ROUND_UP(prate, mode_rate); 111 if (div < 2) { 112 div = 2; 113 } else if (ATMEL_HLCDC_CLKDIV(div) & ~ATMEL_HLCDC_CLKDIV_MASK) { 114 /* The divider ended up too big, try a lower base rate. */ 115 cfg &= ~ATMEL_HLCDC_CLKSEL; 116 prate /= 2; 117 div = DIV_ROUND_UP(prate, mode_rate); 118 if (ATMEL_HLCDC_CLKDIV(div) & ~ATMEL_HLCDC_CLKDIV_MASK) 119 div = ATMEL_HLCDC_CLKDIV_MASK; 120 } else { 121 int div_low = prate / mode_rate; 122 123 if (div_low >= 2 && 124 (10 * (prate / div_low - mode_rate) < 125 (mode_rate - prate / div))) 126 /* 127 * At least 10 times better when using a higher 128 * frequency than requested, instead of a lower. 129 * So, go with that. 130 */ 131 div = div_low; 132 } 133 134 cfg |= ATMEL_HLCDC_CLKDIV(div); 135 136 regmap_update_bits(regmap, ATMEL_HLCDC_CFG(0), mask, cfg); 137 138 state = drm_crtc_state_to_atmel_hlcdc_crtc_state(c->state); 139 cfg = state->output_mode << 8; 140 141 if (adj->flags & DRM_MODE_FLAG_NVSYNC) 142 cfg |= ATMEL_HLCDC_VSPOL; 143 144 if (adj->flags & DRM_MODE_FLAG_NHSYNC) 145 cfg |= ATMEL_HLCDC_HSPOL; 146 147 regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5), 148 ATMEL_HLCDC_HSPOL | ATMEL_HLCDC_VSPOL | 149 ATMEL_HLCDC_VSPDLYS | ATMEL_HLCDC_VSPDLYE | 150 ATMEL_HLCDC_DISPPOL | ATMEL_HLCDC_DISPDLY | 151 ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO | 152 ATMEL_HLCDC_GUARDTIME_MASK | ATMEL_HLCDC_MODE_MASK, 153 cfg); 154 155 clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); 156 } 157 158 static enum drm_mode_status 159 atmel_hlcdc_crtc_mode_valid(struct drm_crtc *c, 160 const struct drm_display_mode *mode) 161 { 162 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 163 164 return atmel_hlcdc_dc_mode_valid(crtc->dc, mode); 165 } 166 167 static void atmel_hlcdc_crtc_atomic_disable(struct drm_crtc *c, 168 struct drm_atomic_state *state) 169 { 170 struct drm_device *dev = c->dev; 171 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 172 struct regmap *regmap = crtc->dc->hlcdc->regmap; 173 unsigned int status; 174 175 drm_crtc_vblank_off(c); 176 177 pm_runtime_get_sync(dev->dev); 178 179 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_DISP); 180 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 181 (status & ATMEL_HLCDC_DISP)) 182 cpu_relax(); 183 184 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_SYNC); 185 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 186 (status & ATMEL_HLCDC_SYNC)) 187 cpu_relax(); 188 189 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PIXEL_CLK); 190 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 191 (status & ATMEL_HLCDC_PIXEL_CLK)) 192 cpu_relax(); 193 194 clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); 195 pinctrl_pm_select_sleep_state(dev->dev); 196 197 pm_runtime_allow(dev->dev); 198 199 pm_runtime_put_sync(dev->dev); 200 } 201 202 static void atmel_hlcdc_crtc_atomic_enable(struct drm_crtc *c, 203 struct drm_atomic_state *state) 204 { 205 struct drm_device *dev = c->dev; 206 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 207 struct regmap *regmap = crtc->dc->hlcdc->regmap; 208 unsigned int status; 209 210 pm_runtime_get_sync(dev->dev); 211 212 pm_runtime_forbid(dev->dev); 213 214 pinctrl_pm_select_default_state(dev->dev); 215 clk_prepare_enable(crtc->dc->hlcdc->sys_clk); 216 217 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PIXEL_CLK); 218 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 219 !(status & ATMEL_HLCDC_PIXEL_CLK)) 220 cpu_relax(); 221 222 223 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_SYNC); 224 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 225 !(status & ATMEL_HLCDC_SYNC)) 226 cpu_relax(); 227 228 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_DISP); 229 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 230 !(status & ATMEL_HLCDC_DISP)) 231 cpu_relax(); 232 233 pm_runtime_put_sync(dev->dev); 234 235 drm_crtc_vblank_on(c); 236 } 237 238 #define ATMEL_HLCDC_RGB444_OUTPUT BIT(0) 239 #define ATMEL_HLCDC_RGB565_OUTPUT BIT(1) 240 #define ATMEL_HLCDC_RGB666_OUTPUT BIT(2) 241 #define ATMEL_HLCDC_RGB888_OUTPUT BIT(3) 242 #define ATMEL_HLCDC_OUTPUT_MODE_MASK GENMASK(3, 0) 243 244 static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state) 245 { 246 struct drm_connector *connector = state->connector; 247 struct drm_display_info *info = &connector->display_info; 248 struct drm_encoder *encoder; 249 unsigned int supported_fmts = 0; 250 int j; 251 252 encoder = state->best_encoder; 253 if (!encoder) 254 encoder = connector->encoder; 255 256 switch (atmel_hlcdc_encoder_get_bus_fmt(encoder)) { 257 case 0: 258 break; 259 case MEDIA_BUS_FMT_RGB444_1X12: 260 return ATMEL_HLCDC_RGB444_OUTPUT; 261 case MEDIA_BUS_FMT_RGB565_1X16: 262 return ATMEL_HLCDC_RGB565_OUTPUT; 263 case MEDIA_BUS_FMT_RGB666_1X18: 264 return ATMEL_HLCDC_RGB666_OUTPUT; 265 case MEDIA_BUS_FMT_RGB888_1X24: 266 return ATMEL_HLCDC_RGB888_OUTPUT; 267 default: 268 return -EINVAL; 269 } 270 271 for (j = 0; j < info->num_bus_formats; j++) { 272 switch (info->bus_formats[j]) { 273 case MEDIA_BUS_FMT_RGB444_1X12: 274 supported_fmts |= ATMEL_HLCDC_RGB444_OUTPUT; 275 break; 276 case MEDIA_BUS_FMT_RGB565_1X16: 277 supported_fmts |= ATMEL_HLCDC_RGB565_OUTPUT; 278 break; 279 case MEDIA_BUS_FMT_RGB666_1X18: 280 supported_fmts |= ATMEL_HLCDC_RGB666_OUTPUT; 281 break; 282 case MEDIA_BUS_FMT_RGB888_1X24: 283 supported_fmts |= ATMEL_HLCDC_RGB888_OUTPUT; 284 break; 285 default: 286 break; 287 } 288 } 289 290 return supported_fmts; 291 } 292 293 static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state) 294 { 295 unsigned int output_fmts = ATMEL_HLCDC_OUTPUT_MODE_MASK; 296 struct atmel_hlcdc_crtc_state *hstate; 297 struct drm_connector_state *cstate; 298 struct drm_connector *connector; 299 struct atmel_hlcdc_crtc *crtc; 300 int i; 301 302 crtc = drm_crtc_to_atmel_hlcdc_crtc(state->crtc); 303 304 for_each_new_connector_in_state(state->state, connector, cstate, i) { 305 unsigned int supported_fmts = 0; 306 307 if (!cstate->crtc) 308 continue; 309 310 supported_fmts = atmel_hlcdc_connector_output_mode(cstate); 311 312 if (crtc->dc->desc->conflicting_output_formats) 313 output_fmts &= supported_fmts; 314 else 315 output_fmts |= supported_fmts; 316 } 317 318 if (!output_fmts) 319 return -EINVAL; 320 321 hstate = drm_crtc_state_to_atmel_hlcdc_crtc_state(state); 322 hstate->output_mode = fls(output_fmts) - 1; 323 324 return 0; 325 } 326 327 static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c, 328 struct drm_atomic_state *state) 329 { 330 struct drm_crtc_state *s = drm_atomic_get_new_crtc_state(state, c); 331 int ret; 332 333 ret = atmel_hlcdc_crtc_select_output_mode(s); 334 if (ret) 335 return ret; 336 337 ret = atmel_hlcdc_plane_prepare_disc_area(s); 338 if (ret) 339 return ret; 340 341 return atmel_hlcdc_plane_prepare_ahb_routing(s); 342 } 343 344 static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c, 345 struct drm_atomic_state *state) 346 { 347 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 348 349 if (c->state->event) { 350 c->state->event->pipe = drm_crtc_index(c); 351 352 WARN_ON(drm_crtc_vblank_get(c) != 0); 353 354 crtc->event = c->state->event; 355 c->state->event = NULL; 356 } 357 } 358 359 static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc, 360 struct drm_atomic_state *state) 361 { 362 /* TODO: write common plane control register if available */ 363 } 364 365 static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = { 366 .mode_valid = atmel_hlcdc_crtc_mode_valid, 367 .mode_set_nofb = atmel_hlcdc_crtc_mode_set_nofb, 368 .atomic_check = atmel_hlcdc_crtc_atomic_check, 369 .atomic_begin = atmel_hlcdc_crtc_atomic_begin, 370 .atomic_flush = atmel_hlcdc_crtc_atomic_flush, 371 .atomic_enable = atmel_hlcdc_crtc_atomic_enable, 372 .atomic_disable = atmel_hlcdc_crtc_atomic_disable, 373 }; 374 375 static void atmel_hlcdc_crtc_destroy(struct drm_crtc *c) 376 { 377 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 378 379 drm_crtc_cleanup(c); 380 kfree(crtc); 381 } 382 383 static void atmel_hlcdc_crtc_finish_page_flip(struct atmel_hlcdc_crtc *crtc) 384 { 385 struct drm_device *dev = crtc->base.dev; 386 unsigned long flags; 387 388 spin_lock_irqsave(&dev->event_lock, flags); 389 if (crtc->event) { 390 drm_crtc_send_vblank_event(&crtc->base, crtc->event); 391 drm_crtc_vblank_put(&crtc->base); 392 crtc->event = NULL; 393 } 394 spin_unlock_irqrestore(&dev->event_lock, flags); 395 } 396 397 void atmel_hlcdc_crtc_irq(struct drm_crtc *c) 398 { 399 drm_crtc_handle_vblank(c); 400 atmel_hlcdc_crtc_finish_page_flip(drm_crtc_to_atmel_hlcdc_crtc(c)); 401 } 402 403 static void atmel_hlcdc_crtc_reset(struct drm_crtc *crtc) 404 { 405 struct atmel_hlcdc_crtc_state *state; 406 407 if (crtc->state) { 408 __drm_atomic_helper_crtc_destroy_state(crtc->state); 409 state = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state); 410 kfree(state); 411 crtc->state = NULL; 412 } 413 414 state = kzalloc(sizeof(*state), GFP_KERNEL); 415 if (state) 416 __drm_atomic_helper_crtc_reset(crtc, &state->base); 417 } 418 419 static struct drm_crtc_state * 420 atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc) 421 { 422 struct atmel_hlcdc_crtc_state *state, *cur; 423 424 if (WARN_ON(!crtc->state)) 425 return NULL; 426 427 state = kmalloc(sizeof(*state), GFP_KERNEL); 428 if (!state) 429 return NULL; 430 __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); 431 432 cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state); 433 state->output_mode = cur->output_mode; 434 435 return &state->base; 436 } 437 438 static void atmel_hlcdc_crtc_destroy_state(struct drm_crtc *crtc, 439 struct drm_crtc_state *s) 440 { 441 struct atmel_hlcdc_crtc_state *state; 442 443 state = drm_crtc_state_to_atmel_hlcdc_crtc_state(s); 444 __drm_atomic_helper_crtc_destroy_state(s); 445 kfree(state); 446 } 447 448 static int atmel_hlcdc_crtc_enable_vblank(struct drm_crtc *c) 449 { 450 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 451 struct regmap *regmap = crtc->dc->hlcdc->regmap; 452 453 /* Enable SOF (Start Of Frame) interrupt for vblank counting */ 454 regmap_write(regmap, ATMEL_HLCDC_IER, ATMEL_HLCDC_SOF); 455 456 return 0; 457 } 458 459 static void atmel_hlcdc_crtc_disable_vblank(struct drm_crtc *c) 460 { 461 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 462 struct regmap *regmap = crtc->dc->hlcdc->regmap; 463 464 regmap_write(regmap, ATMEL_HLCDC_IDR, ATMEL_HLCDC_SOF); 465 } 466 467 static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = { 468 .page_flip = drm_atomic_helper_page_flip, 469 .set_config = drm_atomic_helper_set_config, 470 .destroy = atmel_hlcdc_crtc_destroy, 471 .reset = atmel_hlcdc_crtc_reset, 472 .atomic_duplicate_state = atmel_hlcdc_crtc_duplicate_state, 473 .atomic_destroy_state = atmel_hlcdc_crtc_destroy_state, 474 .enable_vblank = atmel_hlcdc_crtc_enable_vblank, 475 .disable_vblank = atmel_hlcdc_crtc_disable_vblank, 476 .gamma_set = drm_atomic_helper_legacy_gamma_set, 477 }; 478 479 int atmel_hlcdc_crtc_create(struct drm_device *dev) 480 { 481 struct atmel_hlcdc_plane *primary = NULL, *cursor = NULL; 482 struct atmel_hlcdc_dc *dc = dev->dev_private; 483 struct atmel_hlcdc_crtc *crtc; 484 int ret; 485 int i; 486 487 crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); 488 if (!crtc) 489 return -ENOMEM; 490 491 crtc->dc = dc; 492 493 for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) { 494 if (!dc->layers[i]) 495 continue; 496 497 switch (dc->layers[i]->desc->type) { 498 case ATMEL_HLCDC_BASE_LAYER: 499 primary = atmel_hlcdc_layer_to_plane(dc->layers[i]); 500 break; 501 502 case ATMEL_HLCDC_CURSOR_LAYER: 503 cursor = atmel_hlcdc_layer_to_plane(dc->layers[i]); 504 break; 505 506 default: 507 break; 508 } 509 } 510 511 ret = drm_crtc_init_with_planes(dev, &crtc->base, &primary->base, 512 &cursor->base, &atmel_hlcdc_crtc_funcs, 513 NULL); 514 if (ret < 0) 515 goto fail; 516 517 crtc->id = drm_crtc_index(&crtc->base); 518 519 for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) { 520 struct atmel_hlcdc_plane *overlay; 521 522 if (dc->layers[i] && 523 dc->layers[i]->desc->type == ATMEL_HLCDC_OVERLAY_LAYER) { 524 overlay = atmel_hlcdc_layer_to_plane(dc->layers[i]); 525 overlay->base.possible_crtcs = 1 << crtc->id; 526 } 527 } 528 529 drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs); 530 531 drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE); 532 drm_crtc_enable_color_mgmt(&crtc->base, 0, false, 533 ATMEL_HLCDC_CLUT_SIZE); 534 535 dc->crtc = &crtc->base; 536 537 return 0; 538 539 fail: 540 atmel_hlcdc_crtc_destroy(&crtc->base); 541 return ret; 542 } 543