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_crtc_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 = 0; 105 106 prate = clk_get_rate(crtc->dc->hlcdc->sys_clk); 107 mode_rate = adj->crtc_clock * 1000; 108 if ((prate / 2) < mode_rate) { 109 prate *= 2; 110 cfg |= ATMEL_HLCDC_CLKSEL; 111 } 112 113 div = DIV_ROUND_UP(prate, mode_rate); 114 if (div < 2) 115 div = 2; 116 117 cfg |= ATMEL_HLCDC_CLKDIV(div); 118 119 regmap_update_bits(regmap, ATMEL_HLCDC_CFG(0), 120 ATMEL_HLCDC_CLKSEL | ATMEL_HLCDC_CLKDIV_MASK | 121 ATMEL_HLCDC_CLKPOL, cfg); 122 123 cfg = 0; 124 125 if (adj->flags & DRM_MODE_FLAG_NVSYNC) 126 cfg |= ATMEL_HLCDC_VSPOL; 127 128 if (adj->flags & DRM_MODE_FLAG_NHSYNC) 129 cfg |= ATMEL_HLCDC_HSPOL; 130 131 state = drm_crtc_state_to_atmel_hlcdc_crtc_state(c->state); 132 cfg |= state->output_mode << 8; 133 134 regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5), 135 ATMEL_HLCDC_HSPOL | ATMEL_HLCDC_VSPOL | 136 ATMEL_HLCDC_VSPDLYS | ATMEL_HLCDC_VSPDLYE | 137 ATMEL_HLCDC_DISPPOL | ATMEL_HLCDC_DISPDLY | 138 ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO | 139 ATMEL_HLCDC_GUARDTIME_MASK | ATMEL_HLCDC_MODE_MASK, 140 cfg); 141 } 142 143 static bool atmel_hlcdc_crtc_mode_fixup(struct drm_crtc *c, 144 const struct drm_display_mode *mode, 145 struct drm_display_mode *adjusted_mode) 146 { 147 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 148 149 return atmel_hlcdc_dc_mode_valid(crtc->dc, adjusted_mode) == MODE_OK; 150 } 151 152 static void atmel_hlcdc_crtc_disable(struct drm_crtc *c) 153 { 154 struct drm_device *dev = c->dev; 155 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 156 struct regmap *regmap = crtc->dc->hlcdc->regmap; 157 unsigned int status; 158 159 drm_crtc_vblank_off(c); 160 161 pm_runtime_get_sync(dev->dev); 162 163 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_DISP); 164 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 165 (status & ATMEL_HLCDC_DISP)) 166 cpu_relax(); 167 168 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_SYNC); 169 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 170 (status & ATMEL_HLCDC_SYNC)) 171 cpu_relax(); 172 173 regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PIXEL_CLK); 174 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 175 (status & ATMEL_HLCDC_PIXEL_CLK)) 176 cpu_relax(); 177 178 clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); 179 pinctrl_pm_select_sleep_state(dev->dev); 180 181 pm_runtime_allow(dev->dev); 182 183 pm_runtime_put_sync(dev->dev); 184 } 185 186 static void atmel_hlcdc_crtc_enable(struct drm_crtc *c) 187 { 188 struct drm_device *dev = c->dev; 189 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 190 struct regmap *regmap = crtc->dc->hlcdc->regmap; 191 unsigned int status; 192 193 pm_runtime_get_sync(dev->dev); 194 195 pm_runtime_forbid(dev->dev); 196 197 pinctrl_pm_select_default_state(dev->dev); 198 clk_prepare_enable(crtc->dc->hlcdc->sys_clk); 199 200 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PIXEL_CLK); 201 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 202 !(status & ATMEL_HLCDC_PIXEL_CLK)) 203 cpu_relax(); 204 205 206 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_SYNC); 207 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 208 !(status & ATMEL_HLCDC_SYNC)) 209 cpu_relax(); 210 211 regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_DISP); 212 while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && 213 !(status & ATMEL_HLCDC_DISP)) 214 cpu_relax(); 215 216 pm_runtime_put_sync(dev->dev); 217 218 drm_crtc_vblank_on(c); 219 } 220 221 #define ATMEL_HLCDC_RGB444_OUTPUT BIT(0) 222 #define ATMEL_HLCDC_RGB565_OUTPUT BIT(1) 223 #define ATMEL_HLCDC_RGB666_OUTPUT BIT(2) 224 #define ATMEL_HLCDC_RGB888_OUTPUT BIT(3) 225 #define ATMEL_HLCDC_OUTPUT_MODE_MASK GENMASK(3, 0) 226 227 static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state) 228 { 229 unsigned int output_fmts = ATMEL_HLCDC_OUTPUT_MODE_MASK; 230 struct atmel_hlcdc_crtc_state *hstate; 231 struct drm_connector_state *cstate; 232 struct drm_connector *connector; 233 struct atmel_hlcdc_crtc *crtc; 234 int i; 235 236 crtc = drm_crtc_to_atmel_hlcdc_crtc(state->crtc); 237 238 for_each_connector_in_state(state->state, connector, cstate, i) { 239 struct drm_display_info *info = &connector->display_info; 240 unsigned int supported_fmts = 0; 241 int j; 242 243 if (!cstate->crtc) 244 continue; 245 246 for (j = 0; j < info->num_bus_formats; j++) { 247 switch (info->bus_formats[j]) { 248 case MEDIA_BUS_FMT_RGB444_1X12: 249 supported_fmts |= ATMEL_HLCDC_RGB444_OUTPUT; 250 break; 251 case MEDIA_BUS_FMT_RGB565_1X16: 252 supported_fmts |= ATMEL_HLCDC_RGB565_OUTPUT; 253 break; 254 case MEDIA_BUS_FMT_RGB666_1X18: 255 supported_fmts |= ATMEL_HLCDC_RGB666_OUTPUT; 256 break; 257 case MEDIA_BUS_FMT_RGB888_1X24: 258 supported_fmts |= ATMEL_HLCDC_RGB888_OUTPUT; 259 break; 260 default: 261 break; 262 } 263 } 264 265 if (crtc->dc->desc->conflicting_output_formats) 266 output_fmts &= supported_fmts; 267 else 268 output_fmts |= supported_fmts; 269 } 270 271 if (!output_fmts) 272 return -EINVAL; 273 274 hstate = drm_crtc_state_to_atmel_hlcdc_crtc_state(state); 275 hstate->output_mode = fls(output_fmts) - 1; 276 277 return 0; 278 } 279 280 static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c, 281 struct drm_crtc_state *s) 282 { 283 int ret; 284 285 ret = atmel_hlcdc_crtc_select_output_mode(s); 286 if (ret) 287 return ret; 288 289 ret = atmel_hlcdc_plane_prepare_disc_area(s); 290 if (ret) 291 return ret; 292 293 return atmel_hlcdc_plane_prepare_ahb_routing(s); 294 } 295 296 static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c, 297 struct drm_crtc_state *old_s) 298 { 299 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 300 301 if (c->state->event) { 302 c->state->event->pipe = drm_crtc_index(c); 303 304 WARN_ON(drm_crtc_vblank_get(c) != 0); 305 306 crtc->event = c->state->event; 307 c->state->event = NULL; 308 } 309 } 310 311 static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc, 312 struct drm_crtc_state *old_s) 313 { 314 /* TODO: write common plane control register if available */ 315 } 316 317 static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = { 318 .mode_fixup = atmel_hlcdc_crtc_mode_fixup, 319 .mode_set = drm_helper_crtc_mode_set, 320 .mode_set_nofb = atmel_hlcdc_crtc_mode_set_nofb, 321 .mode_set_base = drm_helper_crtc_mode_set_base, 322 .disable = atmel_hlcdc_crtc_disable, 323 .enable = atmel_hlcdc_crtc_enable, 324 .atomic_check = atmel_hlcdc_crtc_atomic_check, 325 .atomic_begin = atmel_hlcdc_crtc_atomic_begin, 326 .atomic_flush = atmel_hlcdc_crtc_atomic_flush, 327 }; 328 329 static void atmel_hlcdc_crtc_destroy(struct drm_crtc *c) 330 { 331 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 332 333 drm_crtc_cleanup(c); 334 kfree(crtc); 335 } 336 337 static void atmel_hlcdc_crtc_finish_page_flip(struct atmel_hlcdc_crtc *crtc) 338 { 339 struct drm_device *dev = crtc->base.dev; 340 unsigned long flags; 341 342 spin_lock_irqsave(&dev->event_lock, flags); 343 if (crtc->event) { 344 drm_crtc_send_vblank_event(&crtc->base, crtc->event); 345 drm_crtc_vblank_put(&crtc->base); 346 crtc->event = NULL; 347 } 348 spin_unlock_irqrestore(&dev->event_lock, flags); 349 } 350 351 void atmel_hlcdc_crtc_irq(struct drm_crtc *c) 352 { 353 drm_crtc_handle_vblank(c); 354 atmel_hlcdc_crtc_finish_page_flip(drm_crtc_to_atmel_hlcdc_crtc(c)); 355 } 356 357 static void atmel_hlcdc_crtc_reset(struct drm_crtc *crtc) 358 { 359 struct atmel_hlcdc_crtc_state *state; 360 361 if (crtc->state) { 362 __drm_atomic_helper_crtc_destroy_state(crtc->state); 363 state = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state); 364 kfree(state); 365 crtc->state = NULL; 366 } 367 368 state = kzalloc(sizeof(*state), GFP_KERNEL); 369 if (state) { 370 crtc->state = &state->base; 371 crtc->state->crtc = crtc; 372 } 373 } 374 375 static struct drm_crtc_state * 376 atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc) 377 { 378 struct atmel_hlcdc_crtc_state *state, *cur; 379 380 if (WARN_ON(!crtc->state)) 381 return NULL; 382 383 state = kmalloc(sizeof(*state), GFP_KERNEL); 384 if (!state) 385 return NULL; 386 __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); 387 388 cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state); 389 state->output_mode = cur->output_mode; 390 391 return &state->base; 392 } 393 394 static void atmel_hlcdc_crtc_destroy_state(struct drm_crtc *crtc, 395 struct drm_crtc_state *s) 396 { 397 struct atmel_hlcdc_crtc_state *state; 398 399 state = drm_crtc_state_to_atmel_hlcdc_crtc_state(s); 400 __drm_atomic_helper_crtc_destroy_state(s); 401 kfree(state); 402 } 403 404 static int atmel_hlcdc_crtc_enable_vblank(struct drm_crtc *c) 405 { 406 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 407 struct regmap *regmap = crtc->dc->hlcdc->regmap; 408 409 /* Enable SOF (Start Of Frame) interrupt for vblank counting */ 410 regmap_write(regmap, ATMEL_HLCDC_IER, ATMEL_HLCDC_SOF); 411 412 return 0; 413 } 414 415 static void atmel_hlcdc_crtc_disable_vblank(struct drm_crtc *c) 416 { 417 struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); 418 struct regmap *regmap = crtc->dc->hlcdc->regmap; 419 420 regmap_write(regmap, ATMEL_HLCDC_IDR, ATMEL_HLCDC_SOF); 421 } 422 423 static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = { 424 .page_flip = drm_atomic_helper_page_flip, 425 .set_config = drm_atomic_helper_set_config, 426 .destroy = atmel_hlcdc_crtc_destroy, 427 .reset = atmel_hlcdc_crtc_reset, 428 .atomic_duplicate_state = atmel_hlcdc_crtc_duplicate_state, 429 .atomic_destroy_state = atmel_hlcdc_crtc_destroy_state, 430 .enable_vblank = atmel_hlcdc_crtc_enable_vblank, 431 .disable_vblank = atmel_hlcdc_crtc_disable_vblank, 432 }; 433 434 int atmel_hlcdc_crtc_create(struct drm_device *dev) 435 { 436 struct atmel_hlcdc_plane *primary = NULL, *cursor = NULL; 437 struct atmel_hlcdc_dc *dc = dev->dev_private; 438 struct atmel_hlcdc_crtc *crtc; 439 int ret; 440 int i; 441 442 crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); 443 if (!crtc) 444 return -ENOMEM; 445 446 crtc->dc = dc; 447 448 for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) { 449 if (!dc->layers[i]) 450 continue; 451 452 switch (dc->layers[i]->desc->type) { 453 case ATMEL_HLCDC_BASE_LAYER: 454 primary = atmel_hlcdc_layer_to_plane(dc->layers[i]); 455 break; 456 457 case ATMEL_HLCDC_CURSOR_LAYER: 458 cursor = atmel_hlcdc_layer_to_plane(dc->layers[i]); 459 break; 460 461 default: 462 break; 463 } 464 } 465 466 ret = drm_crtc_init_with_planes(dev, &crtc->base, &primary->base, 467 &cursor->base, &atmel_hlcdc_crtc_funcs, 468 NULL); 469 if (ret < 0) 470 goto fail; 471 472 crtc->id = drm_crtc_index(&crtc->base); 473 474 for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) { 475 struct atmel_hlcdc_plane *overlay; 476 477 if (dc->layers[i] && 478 dc->layers[i]->desc->type == ATMEL_HLCDC_OVERLAY_LAYER) { 479 overlay = atmel_hlcdc_layer_to_plane(dc->layers[i]); 480 overlay->base.possible_crtcs = 1 << crtc->id; 481 } 482 } 483 484 drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs); 485 drm_crtc_vblank_reset(&crtc->base); 486 487 dc->crtc = &crtc->base; 488 489 return 0; 490 491 fail: 492 atmel_hlcdc_crtc_destroy(&crtc->base); 493 return ret; 494 } 495