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