#define to_vop(x) container_of(x, struct vop, crtc)
#define to_vop_win(x) container_of(x, struct vop_win, base)
-#define to_vop_plane_state(x) container_of(x, struct vop_plane_state, base)
enum vop_pending {
VOP_PENDING_FB_UNREF,
};
-struct vop_plane_state {
- struct drm_plane_state base;
- int format;
- dma_addr_t yrgb_mst;
- bool enable;
-};
-
struct vop_win {
struct drm_plane base;
const struct vop_win_data *data;
struct vop *vop;
-
- /* protected by dev->event_lock */
- bool enable;
- dma_addr_t yrgb_mst;
};
struct vop {
struct drm_crtc_state *crtc_state;
struct drm_framebuffer *fb = state->fb;
struct vop_win *vop_win = to_vop_win(plane);
- struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
const struct vop_win_data *win = vop_win->data;
int ret;
struct drm_rect clip;
DRM_PLANE_HELPER_NO_SCALING;
if (!crtc || !fb)
- goto out_disable;
+ return 0;
crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
if (WARN_ON(!crtc_state))
return ret;
if (!state->visible)
- goto out_disable;
+ return 0;
- vop_plane_state->format = vop_convert_format(fb->pixel_format);
- if (vop_plane_state->format < 0)
- return vop_plane_state->format;
+ ret = vop_convert_format(fb->pixel_format);
+ if (ret < 0)
+ return ret;
/*
* Src.x1 can be odd when do clip, but yuv plane start point
if (is_yuv_support(fb->pixel_format) && ((state->src.x1 >> 16) % 2))
return -EINVAL;
- vop_plane_state->enable = true;
-
- return 0;
-
-out_disable:
- vop_plane_state->enable = false;
return 0;
}
static void vop_plane_atomic_disable(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
- struct vop_plane_state *vop_plane_state = to_vop_plane_state(old_state);
struct vop_win *vop_win = to_vop_win(plane);
const struct vop_win_data *win = vop_win->data;
struct vop *vop = to_vop(old_state->crtc);
if (!old_state->crtc)
return;
- spin_lock_irq(&plane->dev->event_lock);
- vop_win->enable = false;
- vop_win->yrgb_mst = 0;
- spin_unlock_irq(&plane->dev->event_lock);
-
spin_lock(&vop->reg_lock);
VOP_WIN_SET(vop, win, enable, 0);
spin_unlock(&vop->reg_lock);
-
- vop_plane_state->enable = false;
}
static void vop_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *state = plane->state;
struct drm_crtc *crtc = state->crtc;
struct vop_win *vop_win = to_vop_win(plane);
- struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
const struct vop_win_data *win = vop_win->data;
struct vop *vop = to_vop(state->crtc);
struct drm_framebuffer *fb = state->fb;
dma_addr_t dma_addr;
uint32_t val;
bool rb_swap;
+ int format;
/*
* can't update plane when vop is disabled.
if (WARN_ON(!vop->is_enabled))
return;
- if (!vop_plane_state->enable) {
+ if (!state->visible) {
vop_plane_atomic_disable(plane, old_state);
return;
}
offset = (src->x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
offset += (src->y1 >> 16) * fb->pitches[0];
- vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
+ dma_addr = rk_obj->dma_addr + offset + fb->offsets[0];
- spin_lock_irq(&plane->dev->event_lock);
- vop_win->enable = true;
- vop_win->yrgb_mst = vop_plane_state->yrgb_mst;
- spin_unlock_irq(&plane->dev->event_lock);
+ format = vop_convert_format(fb->pixel_format);
spin_lock(&vop->reg_lock);
- VOP_WIN_SET(vop, win, format, vop_plane_state->format);
+ VOP_WIN_SET(vop, win, format, format);
VOP_WIN_SET(vop, win, yrgb_vir, fb->pitches[0] >> 2);
- VOP_WIN_SET(vop, win, yrgb_mst, vop_plane_state->yrgb_mst);
+ VOP_WIN_SET(vop, win, yrgb_mst, dma_addr);
if (is_yuv_support(fb->pixel_format)) {
int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
.atomic_disable = vop_plane_atomic_disable,
};
-static void vop_atomic_plane_reset(struct drm_plane *plane)
-{
- struct vop_plane_state *vop_plane_state =
- to_vop_plane_state(plane->state);
-
- if (plane->state && plane->state->fb)
- drm_framebuffer_unreference(plane->state->fb);
-
- kfree(vop_plane_state);
- vop_plane_state = kzalloc(sizeof(*vop_plane_state), GFP_KERNEL);
- if (!vop_plane_state)
- return;
-
- plane->state = &vop_plane_state->base;
- plane->state->plane = plane;
-}
-
-static struct drm_plane_state *
-vop_atomic_plane_duplicate_state(struct drm_plane *plane)
-{
- struct vop_plane_state *old_vop_plane_state;
- struct vop_plane_state *vop_plane_state;
-
- if (WARN_ON(!plane->state))
- return NULL;
-
- old_vop_plane_state = to_vop_plane_state(plane->state);
- vop_plane_state = kmemdup(old_vop_plane_state,
- sizeof(*vop_plane_state), GFP_KERNEL);
- if (!vop_plane_state)
- return NULL;
-
- __drm_atomic_helper_plane_duplicate_state(plane,
- &vop_plane_state->base);
-
- return &vop_plane_state->base;
-}
-
-static void vop_atomic_plane_destroy_state(struct drm_plane *plane,
- struct drm_plane_state *state)
-{
- struct vop_plane_state *vop_state = to_vop_plane_state(state);
-
- __drm_atomic_helper_plane_destroy_state(state);
-
- kfree(vop_state);
-}
-
static const struct drm_plane_funcs vop_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = vop_plane_destroy,
- .reset = vop_atomic_plane_reset,
- .atomic_duplicate_state = vop_atomic_plane_duplicate_state,
- .atomic_destroy_state = vop_atomic_plane_destroy_state,
+ .reset = drm_atomic_helper_plane_reset,
+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
};
static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
*/
vop_wait_for_irq_handler(vop);
+ spin_lock_irq(&crtc->dev->event_lock);
+ if (crtc->state->event) {
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+ WARN_ON(vop->event);
+
+ vop->event = crtc->state->event;
+ crtc->state->event = NULL;
+ }
+ spin_unlock_irq(&crtc->dev->event_lock);
+
for_each_plane_in_state(old_state, plane, old_plane_state, i) {
if (!old_plane_state->fb)
continue;
static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
- struct vop *vop = to_vop(crtc);
-
rockchip_drm_psr_flush(crtc);
-
- spin_lock_irq(&crtc->dev->event_lock);
- if (crtc->state->event) {
- WARN_ON(drm_crtc_vblank_get(crtc) != 0);
- WARN_ON(vop->event);
-
- vop->event = crtc->state->event;
- crtc->state->event = NULL;
- }
- spin_unlock_irq(&crtc->dev->event_lock);
}
static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
drm_framebuffer_unreference(fb);
}
-static bool vop_win_pending_is_complete(struct vop_win *vop_win)
-{
- dma_addr_t yrgb_mst;
-
- if (!vop_win->enable)
- return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0;
-
- yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win->data);
-
- return yrgb_mst == vop_win->yrgb_mst;
-}
-
static void vop_handle_vblank(struct vop *vop)
{
struct drm_device *drm = vop->drm_dev;
struct drm_crtc *crtc = &vop->crtc;
unsigned long flags;
- int i;
-
- for (i = 0; i < vop->data->win_size; i++) {
- if (!vop_win_pending_is_complete(&vop->win[i]))
- return;
- }
spin_lock_irqsave(&drm->event_lock, flags);
if (vop->event) {
ret = vop_create_crtc(vop);
if (ret)
- return ret;
+ goto err_enable_irq;
pm_runtime_enable(&pdev->dev);
return 0;
+
+err_enable_irq:
+ enable_irq(vop->irq); /* To balance out the disable_irq above */
+ return ret;
}
static void vop_unbind(struct device *dev, struct device *master, void *data)