aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.c118
1 files changed, 117 insertions, 1 deletions
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 9958f2d3d0e8..8b66377a4890 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1138,6 +1138,122 @@ static const struct drm_crtc_funcs armada_crtc_funcs = {
1138 .disable_vblank = armada_drm_crtc_disable_vblank, 1138 .disable_vblank = armada_drm_crtc_disable_vblank,
1139}; 1139};
1140 1140
1141static void armada_drm_primary_update_state(struct drm_plane_state *state,
1142 struct armada_regs *regs)
1143{
1144 struct armada_plane *dplane = drm_to_armada_plane(state->plane);
1145 struct armada_crtc *dcrtc = drm_to_armada_crtc(state->crtc);
1146 struct armada_framebuffer *dfb = drm_fb_to_armada_fb(state->fb);
1147 bool was_disabled;
1148 unsigned int idx = 0;
1149 u32 val;
1150
1151 val = CFG_GRA_FMT(dfb->fmt) | CFG_GRA_MOD(dfb->mod);
1152 if (dfb->fmt > CFG_420)
1153 val |= CFG_PALETTE_ENA;
1154 if (state->visible)
1155 val |= CFG_GRA_ENA;
1156 if (drm_rect_width(&state->src) >> 16 != drm_rect_width(&state->dst))
1157 val |= CFG_GRA_HSMOOTH;
1158
1159 was_disabled = !(dplane->state.ctrl0 & CFG_GRA_ENA);
1160 if (was_disabled)
1161 armada_reg_queue_mod(regs, idx,
1162 0, CFG_PDWN64x66, LCD_SPU_SRAM_PARA1);
1163
1164 dplane->state.ctrl0 = val;
1165 dplane->state.src_hw = (drm_rect_height(&state->src) & 0xffff0000) |
1166 drm_rect_width(&state->src) >> 16;
1167 dplane->state.dst_hw = drm_rect_height(&state->dst) << 16 |
1168 drm_rect_width(&state->dst);
1169 dplane->state.dst_yx = state->dst.y1 << 16 | state->dst.x1;
1170
1171 armada_drm_gra_plane_regs(regs + idx, &dfb->fb, &dplane->state,
1172 state->src.x1 >> 16, state->src.y1 >> 16,
1173 dcrtc->interlaced);
1174
1175 dplane->state.vsync_update = !was_disabled;
1176 dplane->state.changed = true;
1177}
1178
1179static int armada_drm_primary_update(struct drm_plane *plane,
1180 struct drm_crtc *crtc, struct drm_framebuffer *fb,
1181 int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h,
1182 uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
1183 struct drm_modeset_acquire_ctx *ctx)
1184{
1185 struct armada_plane *dplane = drm_to_armada_plane(plane);
1186 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
1187 struct armada_plane_work *work;
1188 struct drm_plane_state state = {
1189 .plane = plane,
1190 .crtc = crtc,
1191 .fb = fb,
1192 .src_x = src_x,
1193 .src_y = src_y,
1194 .src_w = src_w,
1195 .src_h = src_h,
1196 .crtc_x = crtc_x,
1197 .crtc_y = crtc_y,
1198 .crtc_w = crtc_w,
1199 .crtc_h = crtc_h,
1200 .rotation = DRM_MODE_ROTATE_0,
1201 };
1202 const struct drm_rect clip = {
1203 .x2 = crtc->mode.hdisplay,
1204 .y2 = crtc->mode.vdisplay,
1205 };
1206 int ret;
1207
1208 ret = drm_plane_helper_check_state(&state, &clip, 0, INT_MAX, true,
1209 false);
1210 if (ret)
1211 return ret;
1212
1213 work = &dplane->works[dplane->next_work];
1214 work->fn = armada_drm_crtc_complete_frame_work;
1215
1216 if (plane->fb != fb) {
1217 /*
1218 * Take a reference on the new framebuffer - we want to
1219 * hold on to it while the hardware is displaying it.
1220 */
1221 drm_framebuffer_reference(fb);
1222
1223 work->old_fb = plane->fb;
1224 } else {
1225 work->old_fb = NULL;
1226 }
1227
1228 armada_drm_primary_update_state(&state, work->regs);
1229
1230 if (!dplane->state.changed)
1231 return 0;
1232
1233 /* Wait for pending work to complete */
1234 if (armada_drm_plane_work_wait(dplane, HZ / 10) == 0)
1235 armada_drm_plane_work_cancel(dcrtc, dplane);
1236
1237 if (!dplane->state.vsync_update) {
1238 work->fn(dcrtc, work);
1239 if (work->old_fb)
1240 drm_framebuffer_unreference(work->old_fb);
1241 return 0;
1242 }
1243
1244 /* Queue it for update on the next interrupt if we are enabled */
1245 ret = armada_drm_plane_work_queue(dcrtc, work);
1246 if (ret) {
1247 work->fn(dcrtc, work);
1248 if (work->old_fb)
1249 drm_framebuffer_unreference(work->old_fb);
1250 }
1251
1252 dplane->next_work = !dplane->next_work;
1253
1254 return 0;
1255}
1256
1141int armada_drm_plane_disable(struct drm_plane *plane, 1257int armada_drm_plane_disable(struct drm_plane *plane,
1142 struct drm_modeset_acquire_ctx *ctx) 1258 struct drm_modeset_acquire_ctx *ctx)
1143{ 1259{
@@ -1199,7 +1315,7 @@ int armada_drm_plane_disable(struct drm_plane *plane,
1199} 1315}
1200 1316
1201static const struct drm_plane_funcs armada_primary_plane_funcs = { 1317static const struct drm_plane_funcs armada_primary_plane_funcs = {
1202 .update_plane = drm_primary_helper_update, 1318 .update_plane = armada_drm_primary_update,
1203 .disable_plane = armada_drm_plane_disable, 1319 .disable_plane = armada_drm_plane_disable,
1204 .destroy = drm_primary_helper_destroy, 1320 .destroy = drm_primary_helper_destroy,
1205}; 1321};