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