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