0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/clk.h>
0010
0011 #include <drm/drm_atomic.h>
0012 #include <drm/drm_atomic_helper.h>
0013 #include <drm/drm_device.h>
0014 #include <drm/drm_plane_helper.h>
0015 #include <drm/drm_print.h>
0016 #include <drm/drm_probe_helper.h>
0017 #include <drm/drm_vblank.h>
0018
0019 #include "sti_compositor.h"
0020 #include "sti_crtc.h"
0021 #include "sti_drv.h"
0022 #include "sti_vid.h"
0023 #include "sti_vtg.h"
0024
0025 static void sti_crtc_atomic_enable(struct drm_crtc *crtc,
0026 struct drm_atomic_state *state)
0027 {
0028 struct sti_mixer *mixer = to_sti_mixer(crtc);
0029
0030 DRM_DEBUG_DRIVER("\n");
0031
0032 mixer->status = STI_MIXER_READY;
0033
0034 drm_crtc_vblank_on(crtc);
0035 }
0036
0037 static void sti_crtc_atomic_disable(struct drm_crtc *crtc,
0038 struct drm_atomic_state *state)
0039 {
0040 struct sti_mixer *mixer = to_sti_mixer(crtc);
0041
0042 DRM_DEBUG_DRIVER("\n");
0043
0044 mixer->status = STI_MIXER_DISABLING;
0045
0046 drm_crtc_wait_one_vblank(crtc);
0047 }
0048
0049 static int
0050 sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
0051 {
0052 struct sti_mixer *mixer = to_sti_mixer(crtc);
0053 struct device *dev = mixer->dev;
0054 struct sti_compositor *compo = dev_get_drvdata(dev);
0055 struct clk *compo_clk, *pix_clk;
0056 int rate = mode->clock * 1000;
0057
0058 DRM_DEBUG_KMS("CRTC:%d (%s) mode: (%s)\n",
0059 crtc->base.id, sti_mixer_to_str(mixer), mode->name);
0060
0061 DRM_DEBUG_KMS(DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
0062
0063 if (mixer->id == STI_MIXER_MAIN) {
0064 compo_clk = compo->clk_compo_main;
0065 pix_clk = compo->clk_pix_main;
0066 } else {
0067 compo_clk = compo->clk_compo_aux;
0068 pix_clk = compo->clk_pix_aux;
0069 }
0070
0071
0072 if (clk_prepare_enable(compo_clk)) {
0073 DRM_INFO("Failed to prepare/enable compositor clk\n");
0074 goto compo_error;
0075 }
0076
0077
0078 if (clk_set_rate(pix_clk, rate) < 0) {
0079 DRM_ERROR("Cannot set rate (%dHz) for pix clk\n", rate);
0080 goto pix_error;
0081 }
0082 if (clk_prepare_enable(pix_clk)) {
0083 DRM_ERROR("Failed to prepare/enable pix clk\n");
0084 goto pix_error;
0085 }
0086
0087 sti_vtg_set_config(compo->vtg[mixer->id], &crtc->mode);
0088
0089 if (sti_mixer_active_video_area(mixer, &crtc->mode)) {
0090 DRM_ERROR("Can't set active video area\n");
0091 goto mixer_error;
0092 }
0093
0094 return 0;
0095
0096 mixer_error:
0097 clk_disable_unprepare(pix_clk);
0098 pix_error:
0099 clk_disable_unprepare(compo_clk);
0100 compo_error:
0101 return -EINVAL;
0102 }
0103
0104 static void sti_crtc_disable(struct drm_crtc *crtc)
0105 {
0106 struct sti_mixer *mixer = to_sti_mixer(crtc);
0107 struct device *dev = mixer->dev;
0108 struct sti_compositor *compo = dev_get_drvdata(dev);
0109
0110 DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer));
0111
0112
0113 sti_mixer_set_background_status(mixer, false);
0114
0115 drm_crtc_vblank_off(crtc);
0116
0117
0118 if (mixer->id == STI_MIXER_MAIN) {
0119 clk_disable_unprepare(compo->clk_pix_main);
0120 clk_disable_unprepare(compo->clk_compo_main);
0121 } else {
0122 clk_disable_unprepare(compo->clk_pix_aux);
0123 clk_disable_unprepare(compo->clk_compo_aux);
0124 }
0125
0126 mixer->status = STI_MIXER_DISABLED;
0127 }
0128
0129 static void
0130 sti_crtc_mode_set_nofb(struct drm_crtc *crtc)
0131 {
0132 sti_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
0133 }
0134
0135 static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
0136 struct drm_atomic_state *state)
0137 {
0138 struct drm_device *drm_dev = crtc->dev;
0139 struct sti_mixer *mixer = to_sti_mixer(crtc);
0140 struct sti_compositor *compo = dev_get_drvdata(mixer->dev);
0141 struct drm_plane *p;
0142 struct drm_pending_vblank_event *event;
0143 unsigned long flags;
0144
0145 DRM_DEBUG_DRIVER("\n");
0146
0147
0148 list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
0149 struct sti_plane *plane = to_sti_plane(p);
0150
0151 switch (plane->status) {
0152 case STI_PLANE_UPDATED:
0153
0154 if (p->state->crtc != crtc)
0155 continue;
0156
0157
0158 DRM_DEBUG_DRIVER("update plane %s\n",
0159 sti_plane_to_str(plane));
0160
0161 if (sti_mixer_set_plane_depth(mixer, plane)) {
0162 DRM_ERROR("Cannot set plane %s depth\n",
0163 sti_plane_to_str(plane));
0164 break;
0165 }
0166
0167 if (sti_mixer_set_plane_status(mixer, plane, true)) {
0168 DRM_ERROR("Cannot enable plane %s at mixer\n",
0169 sti_plane_to_str(plane));
0170 break;
0171 }
0172
0173
0174 if (plane->desc == STI_HQVDP_0)
0175 sti_vid_commit(compo->vid[0], p->state);
0176
0177 plane->status = STI_PLANE_READY;
0178
0179 break;
0180 case STI_PLANE_DISABLING:
0181
0182 DRM_DEBUG_DRIVER("disable plane %s from mixer\n",
0183 sti_plane_to_str(plane));
0184
0185 if (sti_mixer_set_plane_status(mixer, plane, false)) {
0186 DRM_ERROR("Cannot disable plane %s at mixer\n",
0187 sti_plane_to_str(plane));
0188 continue;
0189 }
0190
0191 if (plane->desc == STI_CURSOR)
0192
0193 plane->status = STI_PLANE_DISABLED;
0194 else
0195
0196 plane->status = STI_PLANE_FLUSHING;
0197
0198
0199 if (plane->desc == STI_HQVDP_0)
0200 sti_vid_disable(compo->vid[0]);
0201
0202 break;
0203 default:
0204
0205 break;
0206 }
0207 }
0208
0209 event = crtc->state->event;
0210 if (event) {
0211 crtc->state->event = NULL;
0212
0213 spin_lock_irqsave(&crtc->dev->event_lock, flags);
0214 if (drm_crtc_vblank_get(crtc) == 0)
0215 drm_crtc_arm_vblank_event(crtc, event);
0216 else
0217 drm_crtc_send_vblank_event(crtc, event);
0218 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
0219 }
0220 }
0221
0222 static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
0223 .mode_set_nofb = sti_crtc_mode_set_nofb,
0224 .atomic_flush = sti_crtc_atomic_flush,
0225 .atomic_enable = sti_crtc_atomic_enable,
0226 .atomic_disable = sti_crtc_atomic_disable,
0227 };
0228
0229 static void sti_crtc_destroy(struct drm_crtc *crtc)
0230 {
0231 DRM_DEBUG_KMS("\n");
0232 drm_crtc_cleanup(crtc);
0233 }
0234
0235 static int sti_crtc_set_property(struct drm_crtc *crtc,
0236 struct drm_property *property,
0237 uint64_t val)
0238 {
0239 DRM_DEBUG_KMS("\n");
0240 return 0;
0241 }
0242
0243 int sti_crtc_vblank_cb(struct notifier_block *nb,
0244 unsigned long event, void *data)
0245 {
0246 struct sti_compositor *compo;
0247 struct drm_crtc *crtc = data;
0248 struct sti_mixer *mixer;
0249 unsigned int pipe;
0250
0251 pipe = drm_crtc_index(crtc);
0252 compo = container_of(nb, struct sti_compositor, vtg_vblank_nb[pipe]);
0253 mixer = compo->mixer[pipe];
0254
0255 if ((event != VTG_TOP_FIELD_EVENT) &&
0256 (event != VTG_BOTTOM_FIELD_EVENT)) {
0257 DRM_ERROR("unknown event: %lu\n", event);
0258 return -EINVAL;
0259 }
0260
0261 drm_crtc_handle_vblank(crtc);
0262
0263 if (mixer->status == STI_MIXER_DISABLING) {
0264 struct drm_plane *p;
0265
0266
0267
0268 list_for_each_entry(p, &crtc->dev->mode_config.plane_list,
0269 head) {
0270 struct sti_plane *plane = to_sti_plane(p);
0271
0272 if ((plane->desc & STI_PLANE_TYPE_MASK) <= STI_VDP)
0273 if (plane->status != STI_PLANE_DISABLED)
0274 return 0;
0275 }
0276 sti_crtc_disable(crtc);
0277 }
0278
0279 return 0;
0280 }
0281
0282 static int sti_crtc_enable_vblank(struct drm_crtc *crtc)
0283 {
0284 struct drm_device *dev = crtc->dev;
0285 unsigned int pipe = crtc->index;
0286 struct sti_private *dev_priv = dev->dev_private;
0287 struct sti_compositor *compo = dev_priv->compo;
0288 struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb[pipe];
0289 struct sti_vtg *vtg = compo->vtg[pipe];
0290
0291 DRM_DEBUG_DRIVER("\n");
0292
0293 if (sti_vtg_register_client(vtg, vtg_vblank_nb, crtc)) {
0294 DRM_ERROR("Cannot register VTG notifier\n");
0295 return -EINVAL;
0296 }
0297
0298 return 0;
0299 }
0300
0301 static void sti_crtc_disable_vblank(struct drm_crtc *crtc)
0302 {
0303 struct drm_device *drm_dev = crtc->dev;
0304 unsigned int pipe = crtc->index;
0305 struct sti_private *priv = drm_dev->dev_private;
0306 struct sti_compositor *compo = priv->compo;
0307 struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb[pipe];
0308 struct sti_vtg *vtg = compo->vtg[pipe];
0309
0310 DRM_DEBUG_DRIVER("\n");
0311
0312 if (sti_vtg_unregister_client(vtg, vtg_vblank_nb))
0313 DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
0314 }
0315
0316 static int sti_crtc_late_register(struct drm_crtc *crtc)
0317 {
0318 struct sti_mixer *mixer = to_sti_mixer(crtc);
0319 struct sti_compositor *compo = dev_get_drvdata(mixer->dev);
0320
0321 if (drm_crtc_index(crtc) == 0)
0322 sti_compositor_debugfs_init(compo, crtc->dev->primary);
0323
0324 return 0;
0325 }
0326
0327 static const struct drm_crtc_funcs sti_crtc_funcs = {
0328 .set_config = drm_atomic_helper_set_config,
0329 .page_flip = drm_atomic_helper_page_flip,
0330 .destroy = sti_crtc_destroy,
0331 .set_property = sti_crtc_set_property,
0332 .reset = drm_atomic_helper_crtc_reset,
0333 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
0334 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
0335 .late_register = sti_crtc_late_register,
0336 .enable_vblank = sti_crtc_enable_vblank,
0337 .disable_vblank = sti_crtc_disable_vblank,
0338 };
0339
0340 bool sti_crtc_is_main(struct drm_crtc *crtc)
0341 {
0342 struct sti_mixer *mixer = to_sti_mixer(crtc);
0343
0344 if (mixer->id == STI_MIXER_MAIN)
0345 return true;
0346
0347 return false;
0348 }
0349
0350 int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
0351 struct drm_plane *primary, struct drm_plane *cursor)
0352 {
0353 struct drm_crtc *crtc = &mixer->drm_crtc;
0354 int res;
0355
0356 res = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
0357 &sti_crtc_funcs, NULL);
0358 if (res) {
0359 DRM_ERROR("Can't initialize CRTC\n");
0360 return -EINVAL;
0361 }
0362
0363 drm_crtc_helper_add(crtc, &sti_crtc_helper_funcs);
0364
0365 DRM_DEBUG_DRIVER("drm CRTC:%d mapped to %s\n",
0366 crtc->base.id, sti_mixer_to_str(mixer));
0367
0368 return 0;
0369 }