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/media-bus-format.h> 12 #include <linux/mfd/atmel-hlcdc.h> 13 #include <linux/pinctrl/consumer.h> 14 #include <linux/pm.h> 15 #include <linux/pm_runtime.h> 16 17 #include <video/videomode.h> 18 19 #include <drm/drm_atomic.h> 20 #include <drm/drm_atomic_helper.h> 21 #include <drm/drm_crtc.h> 22 #include <drm/drm_modeset_helper_vtables.h> 23 #include <drm/drm_print.h> 24 #include <drm/drm_probe_helper.h> 25 #include <drm/drm_vblank.h> 26 27 #include "atmel_hlcdc_dc.h" 28 29 /** 30 * struct atmel_hlcdc_crtc_state - Atmel HLCDC CRTC state structure 31 * 32 * @base: base CRTC state 33 * @output_mode: RGBXXX output mode 34 * @dpi: output DPI mode 35 */ 36 struct atmel_hlcdc_crtc_state { 37 struct drm_crtc_state base; 38 unsigned int output_mode; 39 u8 dpi; 40 }; 41 42 static inline struct atmel_hlcdc_crtc_state * 43 drm_crtc_state_to_atmel_hlcdc_crtc_state(struct drm_crtc_state *state) 44 { 45 return container_of(state, struct atmel_hlcdc_crtc_state, base); 46 } 47 48 /** 49 * struct atmel_hlcdc_crtc - Atmel HLCDC CRTC structure 50 * 51 * @base: base DRM CRTC structure 52 * @dc: pointer to the atmel_hlcdc structure provided by the MFD device 53 * @event: pointer to the current page flip event 54 * @id: CRTC id (returned by drm_crtc_index) 55 */ 56 struct atmel_hlcdc_crtc { 57 struct drm_crtc base; 58 struct atmel_hlcdc_dc *dc; 59 struct drm_pending_vblank_event *event; 60 int id; 61 }; 62 63 static inline struct atmel_hlcdc_crtc * 64 drm_crtc_to_atmel_hlcdc_crtc(struct drm_crtc *crtc) 65 { 66 return container_of(crtc, struct atmel_hlcdc_crtc, base); 67 } 68 69 static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c) 70 { 71 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 72 struct regmap *regmap = crtc->dc->hlcdc->regmap; 73 struct drm_display_mode *adj = &c->state->adjusted_mode; 74 struct drm_encoder *encoder = NULL, *en_iter; 75 struct drm_connector *connector = NULL; 76 struct atmel_hlcdc_crtc_state *state; 77 struct drm_device *ddev = c->dev; 78 struct drm_connector_list_iter iter; 79 unsigned long mode_rate; 80 struct videomode vm; 81 unsigned long prate; 82 unsigned int mask = ATMEL_HLCDC_CLKDIV_MASK | ATMEL_HLCDC_CLKPOL; 83 unsigned int cfg = 0; 84 int div, ret; 85 86 /* get encoder from crtc */ 87 drm_for_each_encoder(en_iter, ddev) { 88 if (en_iter->crtc == c) { 89 encoder = en_iter; 90 break; 91 } 92 } 93 94 if (encoder) { 95 /* Get the connector from encoder */ 96 drm_connector_list_iter_begin(ddev, &iter); 97 drm_for_each_connector_iter(connector, &iter) 98 if (connector->encoder == encoder) 99 break; 100 drm_connector_list_iter_end(&iter); 101 } 102 103 ret = clk_prepare_enable(crtc->dc->hlcdc->sys_clk); 104 if (ret) 105 return; 106 107 vm.vfront_porch = adj->crtc_vsync_start - adj->crtc_vdisplay; 108 vm.vback_porch = adj->crtc_vtotal - adj->crtc_vsync_end; 109 vm.vsync_len = adj->crtc_vsync_end - adj->crtc_vsync_start; 110 vm.hfront_porch = adj->crtc_hsync_start - adj->crtc_hdisplay; 111 vm.hback_porch = adj->crtc_htotal - adj->crtc_hsync_end; 112 vm.hsync_len = adj->crtc_hsync_end - adj->crtc_hsync_start; 113 114 regmap_write(regmap, ATMEL_HLCDC_CFG(1), 115 (vm.hsync_len - 1) | ((vm.vsync_len - 1) << 16)); 116 117 regmap_write(regmap, ATMEL_HLCDC_CFG(2), 118 (vm.vfront_porch - 1) | (vm.vback_porch << 16)); 119 120 regmap_write(regmap, ATMEL_HLCDC_CFG(3), 121 (vm.hfront_porch - 1) | ((vm.hback_porch - 1) << 16)); 122 123 regmap_write(regmap, ATMEL_HLCDC_CFG(4), 124 (adj->crtc_hdisplay - 1) | 125 ((adj->crtc_vdisplay - 1) << 16)); 126 127 prate = clk_get_rate(crtc->dc->hlcdc->sys_clk); 128 mode_rate = adj->crtc_clock * 1000; 129 if (!crtc->dc->desc->fixed_clksrc) { 130 prate *= 2; 131 cfg |= ATMEL_HLCDC_CLKSEL; 132 mask |= ATMEL_HLCDC_CLKSEL; 133 } 134 135 div = DIV_ROUND_UP(prate, mode_rate); 136 if (div < 2) { 137 div = 2; 138 } else if (ATMEL_HLCDC_CLKDIV(div) & ~ATMEL_HLCDC_CLKDIV_MASK) { 139 /* The divider ended up too big, try a lower base rate. */ 140 cfg &= ~ATMEL_HLCDC_CLKSEL; 141 prate /= 2; 142 div = DIV_ROUND_UP(prate, mode_rate); 143 if (ATMEL_HLCDC_CLKDIV(div) & ~ATMEL_HLCDC_CLKDIV_MASK) 144 div = ATMEL_HLCDC_CLKDIV_MASK; 145 } else { 146 int div_low = prate / mode_rate; 147 148 if (div_low >= 2 && 149 (10 * (prate / div_low - mode_rate) < 150 (mode_rate - prate / div))) 151 /* 152 * At least 10 times better when using a higher 153 * frequency than requested, instead of a lower. 154 * So, go with that. 155 */ 156 div = div_low; 157 } 158 159 cfg |= ATMEL_HLCDC_CLKDIV(div); 160 161 if (connector && 162 connector->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) 163 cfg |= ATMEL_HLCDC_CLKPOL; 164 165 regmap_update_bits(regmap, ATMEL_HLCDC_CFG(0), mask, cfg); 166 167 state = drm_crtc_state_to_atmel_hlcdc_crtc_state(c->state); 168 cfg = state->output_mode << 8; 169 170 if (!crtc->dc->desc->is_xlcdc) { 171 if (adj->flags & DRM_MODE_FLAG_NVSYNC) 172 cfg |= ATMEL_HLCDC_VSPOL; 173 174 if (adj->flags & DRM_MODE_FLAG_NHSYNC) 175 cfg |= ATMEL_HLCDC_HSPOL; 176 } else { 177 cfg |= state->dpi << 11; 178 } 179 180 regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5), 181 ATMEL_HLCDC_HSPOL | ATMEL_HLCDC_VSPOL | 182 ATMEL_HLCDC_VSPDLYS | ATMEL_HLCDC_VSPDLYE | 183 ATMEL_HLCDC_DISPPOL | ATMEL_HLCDC_DISPDLY | 184 ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO | 185 ATMEL_HLCDC_GUARDTIME_MASK | 186 (crtc->dc->desc->is_xlcdc ? ATMEL_XLCDC_MODE_MASK | 187 ATMEL_XLCDC_DPI : ATMEL_HLCDC_MODE_MASK), 188 cfg); 189 190 clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); 191 } 192 193 static enum drm_mode_status 194 atmel_hlcdc_crtc_mode_valid(struct drm_crtc *c, 195 const struct drm_display_mode *mode) 196 { 197 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 198 199 return atmel_hlcdc_dc_mode_valid(crtc->dc, mode); 200 } 201 202 static void atmel_hlcdc_crtc_atomic_disable(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 drm_crtc_vblank_off(c); 211 212 pm_runtime_get_sync(dev->dev); 213 214 if (crtc->dc->desc->is_xlcdc) { 215 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_XLCDC_CM); 216 if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, 217 !(status & ATMEL_XLCDC_CM), 218 10, 1000)) 219 drm_warn(dev, "Atmel LCDC status register CMSTS timeout\n"); 220 221 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_XLCDC_SD); 222 if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, 223 status & ATMEL_XLCDC_SD, 224 10, 1000)) 225 drm_warn(dev, "Atmel LCDC status register SDSTS timeout\n"); 226 } 227 228 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_DISP); 229 if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, 230 !(status & ATMEL_HLCDC_DISP), 231 10, 1000)) 232 drm_warn(dev, "Atmel LCDC status register DISPSTS timeout\n"); 233 234 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_SYNC); 235 if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, 236 !(status & ATMEL_HLCDC_SYNC), 237 10, 1000)) 238 drm_warn(dev, "Atmel LCDC status register LCDSTS timeout\n"); 239 240 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PIXEL_CLK); 241 if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, 242 !(status & ATMEL_HLCDC_PIXEL_CLK), 243 10, 1000)) 244 drm_warn(dev, "Atmel LCDC status register CLKSTS timeout\n"); 245 246 clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); 247 pinctrl_pm_select_sleep_state(dev->dev); 248 249 pm_runtime_allow(dev->dev); 250 251 pm_runtime_put_sync(dev->dev); 252 } 253 254 static void atmel_hlcdc_crtc_atomic_enable(struct drm_crtc *c, 255 struct drm_atomic_state *state) 256 { 257 struct drm_device *dev = c->dev; 258 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 259 struct regmap *regmap = crtc->dc->hlcdc->regmap; 260 unsigned int status; 261 262 pm_runtime_get_sync(dev->dev); 263 264 pm_runtime_forbid(dev->dev); 265 266 pinctrl_pm_select_default_state(dev->dev); 267 clk_prepare_enable(crtc->dc->hlcdc->sys_clk); 268 269 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PIXEL_CLK); 270 if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, 271 status & ATMEL_HLCDC_PIXEL_CLK, 272 10, 1000)) 273 drm_warn(dev, "Atmel LCDC status register CLKSTS timeout\n"); 274 275 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_SYNC); 276 if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, 277 status & ATMEL_HLCDC_SYNC, 278 10, 1000)) 279 drm_warn(dev, "Atmel LCDC status register LCDSTS timeout\n"); 280 281 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_DISP); 282 if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, 283 status & ATMEL_HLCDC_DISP, 284 10, 1000)) 285 drm_warn(dev, "Atmel LCDC status register DISPSTS timeout\n"); 286 287 if (crtc->dc->desc->is_xlcdc) { 288 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_XLCDC_CM); 289 if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, 290 status & ATMEL_XLCDC_CM, 291 10, 1000)) 292 drm_warn(dev, "Atmel LCDC status register CMSTS timeout\n"); 293 294 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_XLCDC_SD); 295 if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, 296 !(status & ATMEL_XLCDC_SD), 297 10, 1000)) 298 drm_warn(dev, "Atmel LCDC status register SDSTS timeout\n"); 299 } 300 301 pm_runtime_put_sync(dev->dev); 302 303 } 304 305 #define ATMEL_HLCDC_RGB444_OUTPUT BIT(0) 306 #define ATMEL_HLCDC_RGB565_OUTPUT BIT(1) 307 #define ATMEL_HLCDC_RGB666_OUTPUT BIT(2) 308 #define ATMEL_HLCDC_RGB888_OUTPUT BIT(3) 309 #define ATMEL_HLCDC_DPI_RGB565C1_OUTPUT BIT(4) 310 #define ATMEL_HLCDC_DPI_RGB565C2_OUTPUT BIT(5) 311 #define ATMEL_HLCDC_DPI_RGB565C3_OUTPUT BIT(6) 312 #define ATMEL_HLCDC_DPI_RGB666C1_OUTPUT BIT(7) 313 #define ATMEL_HLCDC_DPI_RGB666C2_OUTPUT BIT(8) 314 #define ATMEL_HLCDC_DPI_RGB888_OUTPUT BIT(9) 315 #define ATMEL_HLCDC_OUTPUT_MODE_MASK GENMASK(3, 0) 316 #define ATMEL_XLCDC_OUTPUT_MODE_MASK GENMASK(9, 0) 317 318 static int atmel_xlcdc_connector_output_dsi(struct drm_encoder *encoder, 319 struct drm_display_info *info) 320 { 321 int j; 322 unsigned int supported_fmts = 0; 323 324 switch (atmel_hlcdc_encoder_get_bus_fmt(encoder)) { 325 case 0: 326 break; 327 case MEDIA_BUS_FMT_RGB565_1X16: 328 return ATMEL_HLCDC_DPI_RGB565C1_OUTPUT; 329 case MEDIA_BUS_FMT_RGB666_1X18: 330 return ATMEL_HLCDC_DPI_RGB666C1_OUTPUT; 331 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 332 return ATMEL_HLCDC_DPI_RGB666C2_OUTPUT; 333 case MEDIA_BUS_FMT_RGB888_1X24: 334 return ATMEL_HLCDC_DPI_RGB888_OUTPUT; 335 default: 336 return -EINVAL; 337 } 338 339 for (j = 0; j < info->num_bus_formats; j++) { 340 switch (info->bus_formats[j]) { 341 case MEDIA_BUS_FMT_RGB565_1X16: 342 supported_fmts |= ATMEL_HLCDC_DPI_RGB565C1_OUTPUT; 343 break; 344 case MEDIA_BUS_FMT_RGB666_1X18: 345 supported_fmts |= ATMEL_HLCDC_DPI_RGB666C1_OUTPUT; 346 break; 347 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 348 supported_fmts |= ATMEL_HLCDC_DPI_RGB666C2_OUTPUT; 349 break; 350 case MEDIA_BUS_FMT_RGB888_1X24: 351 supported_fmts |= ATMEL_HLCDC_DPI_RGB888_OUTPUT; 352 break; 353 default: 354 break; 355 } 356 } 357 return supported_fmts; 358 } 359 360 static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state) 361 { 362 struct drm_connector *connector = state->connector; 363 struct drm_display_info *info = &connector->display_info; 364 struct drm_encoder *encoder; 365 unsigned int supported_fmts = 0; 366 int j; 367 368 encoder = state->best_encoder; 369 if (!encoder) 370 encoder = connector->encoder; 371 /* 372 * atmel-hlcdc to support DSI formats with DSI video pipeline 373 * when DRM_MODE_ENCODER_DSI type is set by 374 * connector driver component. 375 */ 376 if (encoder->encoder_type == DRM_MODE_ENCODER_DSI) 377 return atmel_xlcdc_connector_output_dsi(encoder, info); 378 379 switch (atmel_hlcdc_encoder_get_bus_fmt(encoder)) { 380 case 0: 381 break; 382 case MEDIA_BUS_FMT_RGB444_1X12: 383 return ATMEL_HLCDC_RGB444_OUTPUT; 384 case MEDIA_BUS_FMT_RGB565_1X16: 385 return ATMEL_HLCDC_RGB565_OUTPUT; 386 case MEDIA_BUS_FMT_RGB666_1X18: 387 return ATMEL_HLCDC_RGB666_OUTPUT; 388 case MEDIA_BUS_FMT_RGB888_1X24: 389 return ATMEL_HLCDC_RGB888_OUTPUT; 390 default: 391 return -EINVAL; 392 } 393 394 for (j = 0; j < info->num_bus_formats; j++) { 395 switch (info->bus_formats[j]) { 396 case MEDIA_BUS_FMT_RGB444_1X12: 397 supported_fmts |= ATMEL_HLCDC_RGB444_OUTPUT; 398 break; 399 case MEDIA_BUS_FMT_RGB565_1X16: 400 supported_fmts |= ATMEL_HLCDC_RGB565_OUTPUT; 401 break; 402 case MEDIA_BUS_FMT_RGB666_1X18: 403 supported_fmts |= ATMEL_HLCDC_RGB666_OUTPUT; 404 break; 405 case MEDIA_BUS_FMT_RGB888_1X24: 406 supported_fmts |= ATMEL_HLCDC_RGB888_OUTPUT; 407 break; 408 default: 409 break; 410 } 411 } 412 413 return supported_fmts; 414 } 415 416 static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state) 417 { 418 unsigned int output_fmts; 419 struct atmel_hlcdc_crtc_state *hstate; 420 struct drm_connector_state *cstate; 421 struct drm_connector *connector; 422 struct atmel_hlcdc_crtc *crtc; 423 int i; 424 425 crtc = drm_crtc_to_atmel_hlcdc_crtc(state->crtc); 426 output_fmts = crtc->dc->desc->is_xlcdc ? ATMEL_XLCDC_OUTPUT_MODE_MASK : 427 ATMEL_HLCDC_OUTPUT_MODE_MASK; 428 429 for_each_new_connector_in_state(state->state, connector, cstate, i) { 430 unsigned int supported_fmts = 0; 431 432 if (!cstate->crtc) 433 continue; 434 435 supported_fmts = atmel_hlcdc_connector_output_mode(cstate); 436 437 if (crtc->dc->desc->conflicting_output_formats) 438 output_fmts &= supported_fmts; 439 else 440 output_fmts |= supported_fmts; 441 } 442 443 if (!output_fmts) 444 return -EINVAL; 445 446 hstate = drm_crtc_state_to_atmel_hlcdc_crtc_state(state); 447 hstate->output_mode = fls(output_fmts) - 1; 448 if (crtc->dc->desc->is_xlcdc) { 449 /* check if MIPI DPI bit needs to be set */ 450 if (fls(output_fmts) > 3) { 451 hstate->output_mode -= 4; 452 hstate->dpi = 1; 453 } else { 454 hstate->dpi = 0; 455 } 456 } 457 return 0; 458 } 459 460 static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c, 461 struct drm_atomic_state *state) 462 { 463 struct drm_crtc_state *s = drm_atomic_get_new_crtc_state(state, c); 464 int ret; 465 466 ret = atmel_hlcdc_crtc_select_output_mode(s); 467 if (ret) 468 return ret; 469 470 ret = atmel_hlcdc_plane_prepare_disc_area(s); 471 if (ret) 472 return ret; 473 474 return atmel_hlcdc_plane_prepare_ahb_routing(s); 475 } 476 477 static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c, 478 struct drm_atomic_state *state) 479 { 480 drm_crtc_vblank_on(c); 481 } 482 483 static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *c, 484 struct drm_atomic_state *state) 485 { 486 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 487 unsigned long flags; 488 489 spin_lock_irqsave(&c->dev->event_lock, flags); 490 491 if (c->state->event) { 492 c->state->event->pipe = drm_crtc_index(c); 493 494 WARN_ON(drm_crtc_vblank_get(c) != 0); 495 496 crtc->event = c->state->event; 497 c->state->event = NULL; 498 } 499 spin_unlock_irqrestore(&c->dev->event_lock, flags); 500 } 501 502 static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = { 503 .mode_valid = atmel_hlcdc_crtc_mode_valid, 504 .mode_set_nofb = atmel_hlcdc_crtc_mode_set_nofb, 505 .atomic_check = atmel_hlcdc_crtc_atomic_check, 506 .atomic_begin = atmel_hlcdc_crtc_atomic_begin, 507 .atomic_flush = atmel_hlcdc_crtc_atomic_flush, 508 .atomic_enable = atmel_hlcdc_crtc_atomic_enable, 509 .atomic_disable = atmel_hlcdc_crtc_atomic_disable, 510 }; 511 512 static void atmel_hlcdc_crtc_destroy(struct drm_crtc *c) 513 { 514 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 515 516 drm_crtc_cleanup(c); 517 kfree(crtc); 518 } 519 520 static void atmel_hlcdc_crtc_finish_page_flip(struct atmel_hlcdc_crtc *crtc) 521 { 522 struct drm_device *dev = crtc->base.dev; 523 unsigned long flags; 524 525 spin_lock_irqsave(&dev->event_lock, flags); 526 if (crtc->event) { 527 drm_crtc_send_vblank_event(&crtc->base, crtc->event); 528 drm_crtc_vblank_put(&crtc->base); 529 crtc->event = NULL; 530 } 531 spin_unlock_irqrestore(&dev->event_lock, flags); 532 } 533 534 void atmel_hlcdc_crtc_irq(struct drm_crtc *c) 535 { 536 drm_crtc_handle_vblank(c); 537 atmel_hlcdc_crtc_finish_page_flip(drm_crtc_to_atmel_hlcdc_crtc(c)); 538 } 539 540 static void atmel_hlcdc_crtc_reset(struct drm_crtc *crtc) 541 { 542 struct atmel_hlcdc_crtc_state *state; 543 544 if (crtc->state) { 545 __drm_atomic_helper_crtc_destroy_state(crtc->state); 546 state = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state); 547 kfree(state); 548 crtc->state = NULL; 549 } 550 551 state = kzalloc(sizeof(*state), GFP_KERNEL); 552 if (state) 553 __drm_atomic_helper_crtc_reset(crtc, &state->base); 554 } 555 556 static struct drm_crtc_state * 557 atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc) 558 { 559 struct atmel_hlcdc_crtc_state *state, *cur; 560 struct atmel_hlcdc_crtc *c = drm_crtc_to_atmel_hlcdc_crtc(crtc); 561 562 if (WARN_ON(!crtc->state)) 563 return NULL; 564 565 state = kmalloc(sizeof(*state), GFP_KERNEL); 566 if (!state) 567 return NULL; 568 __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); 569 570 cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state); 571 state->output_mode = cur->output_mode; 572 if (c->dc->desc->is_xlcdc) 573 state->dpi = cur->dpi; 574 575 return &state->base; 576 } 577 578 static void atmel_hlcdc_crtc_destroy_state(struct drm_crtc *crtc, 579 struct drm_crtc_state *s) 580 { 581 struct atmel_hlcdc_crtc_state *state; 582 583 state = drm_crtc_state_to_atmel_hlcdc_crtc_state(s); 584 __drm_atomic_helper_crtc_destroy_state(s); 585 kfree(state); 586 } 587 588 static int atmel_hlcdc_crtc_enable_vblank(struct drm_crtc *c) 589 { 590 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 591 struct regmap *regmap = crtc->dc->hlcdc->regmap; 592 593 /* Enable SOF (Start Of Frame) interrupt for vblank counting */ 594 regmap_write(regmap, ATMEL_HLCDC_IER, ATMEL_HLCDC_SOF); 595 596 return 0; 597 } 598 599 static void atmel_hlcdc_crtc_disable_vblank(struct drm_crtc *c) 600 { 601 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 602 struct regmap *regmap = crtc->dc->hlcdc->regmap; 603 604 regmap_write(regmap, ATMEL_HLCDC_IDR, ATMEL_HLCDC_SOF); 605 } 606 607 static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = { 608 .page_flip = drm_atomic_helper_page_flip, 609 .set_config = drm_atomic_helper_set_config, 610 .destroy = atmel_hlcdc_crtc_destroy, 611 .reset = atmel_hlcdc_crtc_reset, 612 .atomic_duplicate_state = atmel_hlcdc_crtc_duplicate_state, 613 .atomic_destroy_state = atmel_hlcdc_crtc_destroy_state, 614 .enable_vblank = atmel_hlcdc_crtc_enable_vblank, 615 .disable_vblank = atmel_hlcdc_crtc_disable_vblank, 616 }; 617 618 int atmel_hlcdc_crtc_create(struct drm_device *dev) 619 { 620 struct atmel_hlcdc_plane *primary = NULL, *cursor = NULL; 621 struct atmel_hlcdc_dc *dc = dev->dev_private; 622 struct atmel_hlcdc_crtc *crtc; 623 int ret; 624 int i; 625 626 crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); 627 if (!crtc) 628 return -ENOMEM; 629 630 crtc->dc = dc; 631 632 for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) { 633 if (!dc->layers[i]) 634 continue; 635 636 switch (dc->layers[i]->desc->type) { 637 case ATMEL_HLCDC_BASE_LAYER: 638 primary = atmel_hlcdc_layer_to_plane(dc->layers[i]); 639 break; 640 641 case ATMEL_HLCDC_CURSOR_LAYER: 642 cursor = atmel_hlcdc_layer_to_plane(dc->layers[i]); 643 break; 644 645 default: 646 break; 647 } 648 } 649 650 ret = drm_crtc_init_with_planes(dev, &crtc->base, &primary->base, 651 &cursor->base, &atmel_hlcdc_crtc_funcs, 652 NULL); 653 if (ret < 0) 654 goto fail; 655 656 crtc->id = drm_crtc_index(&crtc->base); 657 658 for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) { 659 struct atmel_hlcdc_plane *overlay; 660 661 if (dc->layers[i] && 662 dc->layers[i]->desc->type == ATMEL_HLCDC_OVERLAY_LAYER) { 663 overlay = atmel_hlcdc_layer_to_plane(dc->layers[i]); 664 overlay->base.possible_crtcs = 1 << crtc->id; 665 } 666 } 667 668 drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs); 669 670 drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE); 671 drm_crtc_enable_color_mgmt(&crtc->base, 0, false, 672 ATMEL_HLCDC_CLUT_SIZE); 673 674 dc->crtc = &crtc->base; 675 676 return 0; 677 678 fail: 679 atmel_hlcdc_crtc_destroy(&crtc->base); 680 return ret; 681 } 682