1/* 2 * Copyright (C) STMicroelectronics SA 2014 3 * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> 4 * Fabien Dessenne <fabien.dessenne@st.com> 5 * for STMicroelectronics. 6 * License terms: GNU General Public License (GPL), version 2 7 */ 8 9#include <linux/clk.h> 10 11#include <drm/drmP.h> 12#include <drm/drm_crtc_helper.h> 13 14#include "sti_compositor.h" 15#include "sti_drm_drv.h" 16#include "sti_drm_crtc.h" 17#include "sti_vtg.h" 18 19static void sti_drm_crtc_dpms(struct drm_crtc *crtc, int mode) 20{ 21 DRM_DEBUG_KMS("\n"); 22} 23 24static void sti_drm_crtc_prepare(struct drm_crtc *crtc) 25{ 26 struct sti_mixer *mixer = to_sti_mixer(crtc); 27 struct device *dev = mixer->dev; 28 struct sti_compositor *compo = dev_get_drvdata(dev); 29 30 compo->enable = true; 31 32 /* Prepare and enable the compo IP clock */ 33 if (mixer->id == STI_MIXER_MAIN) { 34 if (clk_prepare_enable(compo->clk_compo_main)) 35 DRM_INFO("Failed to prepare/enable compo_main clk\n"); 36 } else { 37 if (clk_prepare_enable(compo->clk_compo_aux)) 38 DRM_INFO("Failed to prepare/enable compo_aux clk\n"); 39 } 40} 41 42static void sti_drm_crtc_commit(struct drm_crtc *crtc) 43{ 44 struct sti_mixer *mixer = to_sti_mixer(crtc); 45 struct device *dev = mixer->dev; 46 struct sti_compositor *compo = dev_get_drvdata(dev); 47 struct sti_layer *layer; 48 49 if ((!mixer || !compo)) { 50 DRM_ERROR("Can not find mixer or compositor)\n"); 51 return; 52 } 53 54 /* get GDP which is reserved to the CRTC FB */ 55 layer = to_sti_layer(crtc->primary); 56 if (layer) 57 sti_layer_commit(layer); 58 else 59 DRM_ERROR("Can not find CRTC dedicated plane (GDP0)\n"); 60 61 /* Enable layer on mixer */ 62 if (sti_mixer_set_layer_status(mixer, layer, true)) 63 DRM_ERROR("Can not enable layer at mixer\n"); 64} 65 66static bool sti_drm_crtc_mode_fixup(struct drm_crtc *crtc, 67 const struct drm_display_mode *mode, 68 struct drm_display_mode *adjusted_mode) 69{ 70 /* accept the provided drm_display_mode, do not fix it up */ 71 return true; 72} 73 74static int 75sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, 76 struct drm_display_mode *adjusted_mode, int x, int y, 77 struct drm_framebuffer *old_fb) 78{ 79 struct sti_mixer *mixer = to_sti_mixer(crtc); 80 struct device *dev = mixer->dev; 81 struct sti_compositor *compo = dev_get_drvdata(dev); 82 struct sti_layer *layer; 83 struct clk *clk; 84 int rate = mode->clock * 1000; 85 int res; 86 unsigned int w, h; 87 88 DRM_DEBUG_KMS("CRTC:%d (%s) fb:%d mode:%d (%s)\n", 89 crtc->base.id, sti_mixer_to_str(mixer), 90 crtc->primary->fb->base.id, mode->base.id, mode->name); 91 92 DRM_DEBUG_KMS("%d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n", 93 mode->vrefresh, mode->clock, 94 mode->hdisplay, 95 mode->hsync_start, mode->hsync_end, 96 mode->htotal, 97 mode->vdisplay, 98 mode->vsync_start, mode->vsync_end, 99 mode->vtotal, mode->type, mode->flags); 100 101 /* Set rate and prepare/enable pixel clock */ 102 if (mixer->id == STI_MIXER_MAIN) 103 clk = compo->clk_pix_main; 104 else 105 clk = compo->clk_pix_aux; 106 107 res = clk_set_rate(clk, rate); 108 if (res < 0) { 109 DRM_ERROR("Cannot set rate (%dHz) for pix clk\n", rate); 110 return -EINVAL; 111 } 112 if (clk_prepare_enable(clk)) { 113 DRM_ERROR("Failed to prepare/enable pix clk\n"); 114 return -EINVAL; 115 } 116 117 sti_vtg_set_config(mixer->id == STI_MIXER_MAIN ? 118 compo->vtg_main : compo->vtg_aux, &crtc->mode); 119 120 /* a GDP is reserved to the CRTC FB */ 121 layer = to_sti_layer(crtc->primary); 122 if (!layer) { 123 DRM_ERROR("Can not find GDP0)\n"); 124 return -EINVAL; 125 } 126 127 /* copy the mode data adjusted by mode_fixup() into crtc->mode 128 * so that hardware can be set to proper mode 129 */ 130 memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode)); 131 132 res = sti_mixer_set_layer_depth(mixer, layer); 133 if (res) { 134 DRM_ERROR("Can not set layer depth\n"); 135 return -EINVAL; 136 } 137 res = sti_mixer_active_video_area(mixer, &crtc->mode); 138 if (res) { 139 DRM_ERROR("Can not set active video area\n"); 140 return -EINVAL; 141 } 142 143 w = crtc->primary->fb->width - x; 144 h = crtc->primary->fb->height - y; 145 146 return sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode, 147 mixer->id, 0, 0, w, h, x, y, w, h); 148} 149 150static int sti_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, 151 struct drm_framebuffer *old_fb) 152{ 153 struct sti_mixer *mixer = to_sti_mixer(crtc); 154 struct sti_layer *layer; 155 unsigned int w, h; 156 int ret; 157 158 DRM_DEBUG_KMS("CRTC:%d (%s) fb:%d (%d,%d)\n", 159 crtc->base.id, sti_mixer_to_str(mixer), 160 crtc->primary->fb->base.id, x, y); 161 162 /* GDP is reserved to the CRTC FB */ 163 layer = to_sti_layer(crtc->primary); 164 if (!layer) { 165 DRM_ERROR("Can not find GDP0)\n"); 166 ret = -EINVAL; 167 goto out; 168 } 169 170 w = crtc->primary->fb->width - crtc->x; 171 h = crtc->primary->fb->height - crtc->y; 172 173 ret = sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode, 174 mixer->id, 0, 0, w, h, 175 crtc->x, crtc->y, w, h); 176 if (ret) { 177 DRM_ERROR("Can not prepare layer\n"); 178 goto out; 179 } 180 181 sti_drm_crtc_commit(crtc); 182out: 183 return ret; 184} 185 186static void sti_drm_crtc_load_lut(struct drm_crtc *crtc) 187{ 188 /* do nothing */ 189} 190 191static void sti_drm_crtc_disable(struct drm_crtc *crtc) 192{ 193 struct sti_mixer *mixer = to_sti_mixer(crtc); 194 struct device *dev = mixer->dev; 195 struct sti_compositor *compo = dev_get_drvdata(dev); 196 struct sti_layer *layer; 197 198 if (!compo->enable) 199 return; 200 201 DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer)); 202 203 /* Disable Background */ 204 sti_mixer_set_background_status(mixer, false); 205 206 /* Disable GDP */ 207 layer = to_sti_layer(crtc->primary); 208 if (!layer) { 209 DRM_ERROR("Cannot find GDP0\n"); 210 return; 211 } 212 213 /* Disable layer at mixer level */ 214 if (sti_mixer_set_layer_status(mixer, layer, false)) 215 DRM_ERROR("Can not disable %s layer at mixer\n", 216 sti_layer_to_str(layer)); 217 218 /* Wait a while to be sure that a Vsync event is received */ 219 msleep(WAIT_NEXT_VSYNC_MS); 220 221 /* Then disable layer itself */ 222 sti_layer_disable(layer); 223 224 drm_vblank_off(crtc->dev, mixer->id); 225 226 /* Disable pixel clock and compo IP clocks */ 227 if (mixer->id == STI_MIXER_MAIN) { 228 clk_disable_unprepare(compo->clk_pix_main); 229 clk_disable_unprepare(compo->clk_compo_main); 230 } else { 231 clk_disable_unprepare(compo->clk_pix_aux); 232 clk_disable_unprepare(compo->clk_compo_aux); 233 } 234 235 compo->enable = false; 236} 237 238static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { 239 .dpms = sti_drm_crtc_dpms, 240 .prepare = sti_drm_crtc_prepare, 241 .commit = sti_drm_crtc_commit, 242 .mode_fixup = sti_drm_crtc_mode_fixup, 243 .mode_set = sti_drm_crtc_mode_set, 244 .mode_set_base = sti_drm_crtc_mode_set_base, 245 .load_lut = sti_drm_crtc_load_lut, 246 .disable = sti_drm_crtc_disable, 247}; 248 249static int sti_drm_crtc_page_flip(struct drm_crtc *crtc, 250 struct drm_framebuffer *fb, 251 struct drm_pending_vblank_event *event, 252 uint32_t page_flip_flags) 253{ 254 struct drm_device *drm_dev = crtc->dev; 255 struct drm_framebuffer *old_fb; 256 struct sti_mixer *mixer = to_sti_mixer(crtc); 257 unsigned long flags; 258 int ret; 259 260 DRM_DEBUG_KMS("fb %d --> fb %d\n", 261 crtc->primary->fb->base.id, fb->base.id); 262 263 mutex_lock(&drm_dev->struct_mutex); 264 265 old_fb = crtc->primary->fb; 266 crtc->primary->fb = fb; 267 ret = sti_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb); 268 if (ret) { 269 DRM_ERROR("failed\n"); 270 crtc->primary->fb = old_fb; 271 goto out; 272 } 273 274 if (event) { 275 event->pipe = mixer->id; 276 277 ret = drm_vblank_get(drm_dev, event->pipe); 278 if (ret) { 279 DRM_ERROR("Cannot get vblank\n"); 280 goto out; 281 } 282 283 spin_lock_irqsave(&drm_dev->event_lock, flags); 284 if (mixer->pending_event) { 285 drm_vblank_put(drm_dev, event->pipe); 286 ret = -EBUSY; 287 } else { 288 mixer->pending_event = event; 289 } 290 spin_unlock_irqrestore(&drm_dev->event_lock, flags); 291 } 292out: 293 mutex_unlock(&drm_dev->struct_mutex); 294 return ret; 295} 296 297static void sti_drm_crtc_destroy(struct drm_crtc *crtc) 298{ 299 DRM_DEBUG_KMS("\n"); 300 drm_crtc_cleanup(crtc); 301} 302 303static int sti_drm_crtc_set_property(struct drm_crtc *crtc, 304 struct drm_property *property, 305 uint64_t val) 306{ 307 DRM_DEBUG_KMS("\n"); 308 return 0; 309} 310 311int sti_drm_crtc_vblank_cb(struct notifier_block *nb, 312 unsigned long event, void *data) 313{ 314 struct drm_device *drm_dev; 315 struct sti_compositor *compo = 316 container_of(nb, struct sti_compositor, vtg_vblank_nb); 317 int *crtc = data; 318 unsigned long flags; 319 struct sti_drm_private *priv; 320 321 drm_dev = compo->mixer[*crtc]->drm_crtc.dev; 322 priv = drm_dev->dev_private; 323 324 if ((event != VTG_TOP_FIELD_EVENT) && 325 (event != VTG_BOTTOM_FIELD_EVENT)) { 326 DRM_ERROR("unknown event: %lu\n", event); 327 return -EINVAL; 328 } 329 330 drm_handle_vblank(drm_dev, *crtc); 331 332 spin_lock_irqsave(&drm_dev->event_lock, flags); 333 if (compo->mixer[*crtc]->pending_event) { 334 drm_send_vblank_event(drm_dev, -1, 335 compo->mixer[*crtc]->pending_event); 336 drm_vblank_put(drm_dev, *crtc); 337 compo->mixer[*crtc]->pending_event = NULL; 338 } 339 spin_unlock_irqrestore(&drm_dev->event_lock, flags); 340 341 return 0; 342} 343 344int sti_drm_crtc_enable_vblank(struct drm_device *dev, int crtc) 345{ 346 struct sti_drm_private *dev_priv = dev->dev_private; 347 struct sti_compositor *compo = dev_priv->compo; 348 struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb; 349 350 if (sti_vtg_register_client(crtc == STI_MIXER_MAIN ? 351 compo->vtg_main : compo->vtg_aux, 352 vtg_vblank_nb, crtc)) { 353 DRM_ERROR("Cannot register VTG notifier\n"); 354 return -EINVAL; 355 } 356 357 return 0; 358} 359EXPORT_SYMBOL(sti_drm_crtc_enable_vblank); 360 361void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc) 362{ 363 struct sti_drm_private *priv = dev->dev_private; 364 struct sti_compositor *compo = priv->compo; 365 struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb; 366 unsigned long flags; 367 368 DRM_DEBUG_DRIVER("\n"); 369 370 if (sti_vtg_unregister_client(crtc == STI_MIXER_MAIN ? 371 compo->vtg_main : compo->vtg_aux, vtg_vblank_nb)) 372 DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n"); 373 374 /* free the resources of the pending requests */ 375 spin_lock_irqsave(&dev->event_lock, flags); 376 if (compo->mixer[crtc]->pending_event) { 377 drm_vblank_put(dev, crtc); 378 compo->mixer[crtc]->pending_event = NULL; 379 } 380 spin_unlock_irqrestore(&dev->event_lock, flags); 381 382} 383EXPORT_SYMBOL(sti_drm_crtc_disable_vblank); 384 385static struct drm_crtc_funcs sti_crtc_funcs = { 386 .set_config = drm_crtc_helper_set_config, 387 .page_flip = sti_drm_crtc_page_flip, 388 .destroy = sti_drm_crtc_destroy, 389 .set_property = sti_drm_crtc_set_property, 390}; 391 392bool sti_drm_crtc_is_main(struct drm_crtc *crtc) 393{ 394 struct sti_mixer *mixer = to_sti_mixer(crtc); 395 396 if (mixer->id == STI_MIXER_MAIN) 397 return true; 398 399 return false; 400} 401 402int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer, 403 struct drm_plane *primary, struct drm_plane *cursor) 404{ 405 struct drm_crtc *crtc = &mixer->drm_crtc; 406 int res; 407 408 res = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor, 409 &sti_crtc_funcs); 410 if (res) { 411 DRM_ERROR("Can not initialze CRTC\n"); 412 return -EINVAL; 413 } 414 415 drm_crtc_helper_add(crtc, &sti_crtc_helper_funcs); 416 417 DRM_DEBUG_DRIVER("drm CRTC:%d mapped to %s\n", 418 crtc->base.id, sti_mixer_to_str(mixer)); 419 420 return 0; 421} 422