1 /* 2 * Copyright (C) 2014 Traphandler 3 * Copyright (C) 2014 Free Electrons 4 * 5 * Author: Jean-Jacques Hiblot <jjhiblot@traphandler.com> 6 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License version 2 as published by 10 * the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along with 18 * this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include <linux/clk.h> 22 #include <linux/pm.h> 23 #include <linux/pm_runtime.h> 24 #include <linux/pinctrl/consumer.h> 25 26 #include <drm/drm_crtc.h> 27 #include <drm/drm_probe_helper.h> 28 #include <drm/drmP.h> 29 30 #include <video/videomode.h> 31 32 #include "atmel_hlcdc_dc.h" 33 34 /** 35 * Atmel HLCDC CRTC state structure 36 * 37 * @base: base CRTC state 38 * @output_mode: RGBXXX output mode 39 */ 40 struct atmel_hlcdc_crtc_state { 41 struct drm_crtc_state base; 42 unsigned int output_mode; 43 }; 44 45 static inline struct atmel_hlcdc_crtc_state * 46 drm_crtc_state_to_atmel_hlcdc_crtc_state(struct drm_crtc_state *state) 47 { 48 return container_of(state, struct atmel_hlcdc_crtc_state, base); 49 } 50 51 /** 52 * Atmel HLCDC CRTC structure 53 * 54 * @base: base DRM CRTC structure 55 * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device 56 * @event: pointer to the current page flip event 57 * @id: CRTC id (returned by drm_crtc_index) 58 */ 59 struct atmel_hlcdc_crtc { 60 struct drm_crtc base; 61 struct atmel_hlcdc_dc *dc; 62 struct drm_pending_vblank_event *event; 63 int id; 64 }; 65 66 static inline struct atmel_hlcdc_crtc * 67 drm_crtc_to_atmel_hlcdc_crtc(struct drm_crtc *crtc) 68 { 69 return container_of(crtc, struct atmel_hlcdc_crtc, base); 70 } 71 72 static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c) 73 { 74 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 75 struct regmap *regmap = crtc->dc->hlcdc->regmap; 76 struct drm_display_mode *adj = &c->state->adjusted_mode; 77 struct atmel_hlcdc_crtc_state *state; 78 unsigned long mode_rate; 79 struct videomode vm; 80 unsigned long prate; 81 unsigned int cfg; 82 int div; 83 84 vm.vfront_porch = adj->crtc_vsync_start - adj->crtc_vdisplay; 85 vm.vback_porch = adj->crtc_vtotal - adj->crtc_vsync_end; 86 vm.vsync_len = adj->crtc_vsync_end - adj->crtc_vsync_start; 87 vm.hfront_porch = adj->crtc_hsync_start - adj->crtc_hdisplay; 88 vm.hback_porch = adj->crtc_htotal - adj->crtc_hsync_end; 89 vm.hsync_len = adj->crtc_hsync_end - adj->crtc_hsync_start; 90 91 regmap_write(regmap, ATMEL_HLCDC_CFG(1), 92 (vm.hsync_len - 1) | ((vm.vsync_len - 1) << 16)); 93 94 regmap_write(regmap, ATMEL_HLCDC_CFG(2), 95 (vm.vfront_porch - 1) | (vm.vback_porch << 16)); 96 97 regmap_write(regmap, ATMEL_HLCDC_CFG(3), 98 (vm.hfront_porch - 1) | ((vm.hback_porch - 1) << 16)); 99 100 regmap_write(regmap, ATMEL_HLCDC_CFG(4), 101 (adj->crtc_hdisplay - 1) | 102 ((adj->crtc_vdisplay - 1) << 16)); 103 104 cfg = ATMEL_HLCDC_CLKSEL; 105 106 prate = 2 * clk_get_rate(crtc->dc->hlcdc->sys_clk); 107 mode_rate = adj->crtc_clock * 1000; 108 109 div = DIV_ROUND_UP(prate, mode_rate); 110 if (div < 2) { 111 div = 2; 112 } else if (ATMEL_HLCDC_CLKDIV(div) & ~ATMEL_HLCDC_CLKDIV_MASK) { 113 /* The divider ended up too big, try a lower base rate. */ 114 cfg &= ~ATMEL_HLCDC_CLKSEL; 115 prate /= 2; 116 div = DIV_ROUND_UP(prate, mode_rate); 117 if (ATMEL_HLCDC_CLKDIV(div) & ~ATMEL_HLCDC_CLKDIV_MASK) 118 div = ATMEL_HLCDC_CLKDIV_MASK; 119 } else { 120 int div_low = prate / mode_rate; 121 122 if (div_low >= 2 && 123 ((prate / div_low - mode_rate) < 124 10 * (mode_rate - prate / div))) 125 /* 126 * At least 10 times better when using a higher 127 * frequency than requested, instead of a lower. 128 * So, go with that. 129 */ 130 div = div_low; 131 } 132 133 cfg |= ATMEL_HLCDC_CLKDIV(div); 134 135 regmap_update_bits(regmap, ATMEL_HLCDC_CFG(0), 136 ATMEL_HLCDC_CLKSEL | ATMEL_HLCDC_CLKDIV_MASK | 137 ATMEL_HLCDC_CLKPOL, cfg); 138 139 cfg = 0; 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 state = drm_crtc_state_to_atmel_hlcdc_crtc_state(c->state); 148 cfg |= state->output_mode << 8; 149 150 regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5), 151 ATMEL_HLCDC_HSPOL | ATMEL_HLCDC_VSPOL | 152 ATMEL_HLCDC_VSPDLYS | ATMEL_HLCDC_VSPDLYE | 153 ATMEL_HLCDC_DISPPOL | ATMEL_HLCDC_DISPDLY | 154 ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO | 155 ATMEL_HLCDC_GUARDTIME_MASK | ATMEL_HLCDC_MODE_MASK, 156 cfg); 157 } 158 159 static enum drm_mode_status 160 atmel_hlcdc_crtc_mode_valid(struct drm_crtc *c, 161 const struct drm_display_mode *mode) 162 { 163 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 164 165 return atmel_hlcdc_dc_mode_valid(crtc->dc, mode); 166 } 167 168 static void atmel_hlcdc_crtc_atomic_disable(struct drm_crtc *c, 169 struct drm_crtc_state *old_state) 170 { 171 struct drm_device *dev = c->dev; 172 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 173 struct regmap *regmap = crtc->dc->hlcdc->regmap; 174 unsigned int status; 175 176 drm_crtc_vblank_off(c); 177 178 pm_runtime_get_sync(dev->dev); 179 180 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_DISP); 181 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 182 (status & ATMEL_HLCDC_DISP)) 183 cpu_relax(); 184 185 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_SYNC); 186 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 187 (status & ATMEL_HLCDC_SYNC)) 188 cpu_relax(); 189 190 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PIXEL_CLK); 191 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 192 (status & ATMEL_HLCDC_PIXEL_CLK)) 193 cpu_relax(); 194 195 clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); 196 pinctrl_pm_select_sleep_state(dev->dev); 197 198 pm_runtime_allow(dev->dev); 199 200 pm_runtime_put_sync(dev->dev); 201 } 202 203 static void atmel_hlcdc_crtc_atomic_enable(struct drm_crtc *c, 204 struct drm_crtc_state *old_state) 205 { 206 struct drm_device *dev = c->dev; 207 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 208 struct regmap *regmap = crtc->dc->hlcdc->regmap; 209 unsigned int status; 210 211 pm_runtime_get_sync(dev->dev); 212 213 pm_runtime_forbid(dev->dev); 214 215 pinctrl_pm_select_default_state(dev->dev); 216 clk_prepare_enable(crtc->dc->hlcdc->sys_clk); 217 218 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PIXEL_CLK); 219 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 220 !(status & ATMEL_HLCDC_PIXEL_CLK)) 221 cpu_relax(); 222 223 224 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_SYNC); 225 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 226 !(status & ATMEL_HLCDC_SYNC)) 227 cpu_relax(); 228 229 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_DISP); 230 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 231 !(status & ATMEL_HLCDC_DISP)) 232 cpu_relax(); 233 234 pm_runtime_put_sync(dev->dev); 235 236 drm_crtc_vblank_on(c); 237 } 238 239 #define ATMEL_HLCDC_RGB444_OUTPUT BIT(0) 240 #define ATMEL_HLCDC_RGB565_OUTPUT BIT(1) 241 #define ATMEL_HLCDC_RGB666_OUTPUT BIT(2) 242 #define ATMEL_HLCDC_RGB888_OUTPUT BIT(3) 243 #define ATMEL_HLCDC_OUTPUT_MODE_MASK GENMASK(3, 0) 244 245 static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state) 246 { 247 struct drm_connector *connector = state->connector; 248 struct drm_display_info *info = &connector->display_info; 249 struct drm_encoder *encoder; 250 unsigned int supported_fmts = 0; 251 int j; 252 253 encoder = state->best_encoder; 254 if (!encoder) 255 encoder = connector->encoder; 256 257 switch (atmel_hlcdc_encoder_get_bus_fmt(encoder)) { 258 case 0: 259 break; 260 case MEDIA_BUS_FMT_RGB444_1X12: 261 return ATMEL_HLCDC_RGB444_OUTPUT; 262 case MEDIA_BUS_FMT_RGB565_1X16: 263 return ATMEL_HLCDC_RGB565_OUTPUT; 264 case MEDIA_BUS_FMT_RGB666_1X18: 265 return ATMEL_HLCDC_RGB666_OUTPUT; 266 case MEDIA_BUS_FMT_RGB888_1X24: 267 return ATMEL_HLCDC_RGB888_OUTPUT; 268 default: 269 return -EINVAL; 270 } 271 272 for (j = 0; j < info->num_bus_formats; j++) { 273 switch (info->bus_formats[j]) { 274 case MEDIA_BUS_FMT_RGB444_1X12: 275 supported_fmts |= ATMEL_HLCDC_RGB444_OUTPUT; 276 break; 277 case MEDIA_BUS_FMT_RGB565_1X16: 278 supported_fmts |= ATMEL_HLCDC_RGB565_OUTPUT; 279 break; 280 case MEDIA_BUS_FMT_RGB666_1X18: 281 supported_fmts |= ATMEL_HLCDC_RGB666_OUTPUT; 282 break; 283 case MEDIA_BUS_FMT_RGB888_1X24: 284 supported_fmts |= ATMEL_HLCDC_RGB888_OUTPUT; 285 break; 286 default: 287 break; 288 } 289 } 290 291 return supported_fmts; 292 } 293 294 static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state) 295 { 296 unsigned int output_fmts = ATMEL_HLCDC_OUTPUT_MODE_MASK; 297 struct atmel_hlcdc_crtc_state *hstate; 298 struct drm_connector_state *cstate; 299 struct drm_connector *connector; 300 struct atmel_hlcdc_crtc *crtc; 301 int i; 302 303 crtc = drm_crtc_to_atmel_hlcdc_crtc(state->crtc); 304 305 for_each_new_connector_in_state(state->state, connector, cstate, i) { 306 unsigned int supported_fmts = 0; 307 308 if (!cstate->crtc) 309 continue; 310 311 supported_fmts = atmel_hlcdc_connector_output_mode(cstate); 312 313 if (crtc->dc->desc->conflicting_output_formats) 314 output_fmts &= supported_fmts; 315 else 316 output_fmts |= supported_fmts; 317 } 318 319 if (!output_fmts) 320 return -EINVAL; 321 322 hstate = drm_crtc_state_to_atmel_hlcdc_crtc_state(state); 323 hstate->output_mode = fls(output_fmts) - 1; 324 325 return 0; 326 } 327 328 static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c, 329 struct drm_crtc_state *s) 330 { 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_crtc_state *old_s) 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_crtc_state *old_s) 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 crtc->state = &state->base; 417 crtc->state->crtc = crtc; 418 } 419 } 420 421 static struct drm_crtc_state * 422 atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc) 423 { 424 struct atmel_hlcdc_crtc_state *state, *cur; 425 426 if (WARN_ON(!crtc->state)) 427 return NULL; 428 429 state = kmalloc(sizeof(*state), GFP_KERNEL); 430 if (!state) 431 return NULL; 432 __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); 433 434 cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state); 435 state->output_mode = cur->output_mode; 436 437 return &state->base; 438 } 439 440 static void atmel_hlcdc_crtc_destroy_state(struct drm_crtc *crtc, 441 struct drm_crtc_state *s) 442 { 443 struct atmel_hlcdc_crtc_state *state; 444 445 state = drm_crtc_state_to_atmel_hlcdc_crtc_state(s); 446 __drm_atomic_helper_crtc_destroy_state(s); 447 kfree(state); 448 } 449 450 static int atmel_hlcdc_crtc_enable_vblank(struct drm_crtc *c) 451 { 452 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 453 struct regmap *regmap = crtc->dc->hlcdc->regmap; 454 455 /* Enable SOF (Start Of Frame) interrupt for vblank counting */ 456 regmap_write(regmap, ATMEL_HLCDC_IER, ATMEL_HLCDC_SOF); 457 458 return 0; 459 } 460 461 static void atmel_hlcdc_crtc_disable_vblank(struct drm_crtc *c) 462 { 463 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 464 struct regmap *regmap = crtc->dc->hlcdc->regmap; 465 466 regmap_write(regmap, ATMEL_HLCDC_IDR, ATMEL_HLCDC_SOF); 467 } 468 469 static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = { 470 .page_flip = drm_atomic_helper_page_flip, 471 .set_config = drm_atomic_helper_set_config, 472 .destroy = atmel_hlcdc_crtc_destroy, 473 .reset = atmel_hlcdc_crtc_reset, 474 .atomic_duplicate_state = atmel_hlcdc_crtc_duplicate_state, 475 .atomic_destroy_state = atmel_hlcdc_crtc_destroy_state, 476 .enable_vblank = atmel_hlcdc_crtc_enable_vblank, 477 .disable_vblank = atmel_hlcdc_crtc_disable_vblank, 478 .gamma_set = drm_atomic_helper_legacy_gamma_set, 479 }; 480 481 int atmel_hlcdc_crtc_create(struct drm_device *dev) 482 { 483 struct atmel_hlcdc_plane *primary = NULL, *cursor = NULL; 484 struct atmel_hlcdc_dc *dc = dev->dev_private; 485 struct atmel_hlcdc_crtc *crtc; 486 int ret; 487 int i; 488 489 crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); 490 if (!crtc) 491 return -ENOMEM; 492 493 crtc->dc = dc; 494 495 for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) { 496 if (!dc->layers[i]) 497 continue; 498 499 switch (dc->layers[i]->desc->type) { 500 case ATMEL_HLCDC_BASE_LAYER: 501 primary = atmel_hlcdc_layer_to_plane(dc->layers[i]); 502 break; 503 504 case ATMEL_HLCDC_CURSOR_LAYER: 505 cursor = atmel_hlcdc_layer_to_plane(dc->layers[i]); 506 break; 507 508 default: 509 break; 510 } 511 } 512 513 ret = drm_crtc_init_with_planes(dev, &crtc->base, &primary->base, 514 &cursor->base, &atmel_hlcdc_crtc_funcs, 515 NULL); 516 if (ret < 0) 517 goto fail; 518 519 crtc->id = drm_crtc_index(&crtc->base); 520 521 for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) { 522 struct atmel_hlcdc_plane *overlay; 523 524 if (dc->layers[i] && 525 dc->layers[i]->desc->type == ATMEL_HLCDC_OVERLAY_LAYER) { 526 overlay = atmel_hlcdc_layer_to_plane(dc->layers[i]); 527 overlay->base.possible_crtcs = 1 << crtc->id; 528 } 529 } 530 531 drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs); 532 drm_crtc_vblank_reset(&crtc->base); 533 534 drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE); 535 drm_crtc_enable_color_mgmt(&crtc->base, 0, false, 536 ATMEL_HLCDC_CLUT_SIZE); 537 538 dc->crtc = &crtc->base; 539 540 return 0; 541 542 fail: 543 atmel_hlcdc_crtc_destroy(&crtc->base); 544 return ret; 545 } 546