1*b961c48bSJyri Sarha /* 2*b961c48bSJyri Sarha * Copyright (C) 2015 Texas Instruments 3*b961c48bSJyri Sarha * Author: Jyri Sarha <jsarha@ti.com> 4*b961c48bSJyri Sarha * 5*b961c48bSJyri Sarha * This program is free software; you can redistribute it and/or modify it 6*b961c48bSJyri Sarha * under the terms of the GNU General Public License version 2 as published by 7*b961c48bSJyri Sarha * the Free Software Foundation. 8*b961c48bSJyri Sarha * 9*b961c48bSJyri Sarha * This program is distributed in the hope that it will be useful, but WITHOUT 10*b961c48bSJyri Sarha * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11*b961c48bSJyri Sarha * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12*b961c48bSJyri Sarha * more details. 13*b961c48bSJyri Sarha * 14*b961c48bSJyri Sarha * You should have received a copy of the GNU General Public License along with 15*b961c48bSJyri Sarha * this program. If not, see <http://www.gnu.org/licenses/>. 16*b961c48bSJyri Sarha */ 17*b961c48bSJyri Sarha 18*b961c48bSJyri Sarha #include <drm/drmP.h> 19*b961c48bSJyri Sarha 20*b961c48bSJyri Sarha #include <drm/drm_atomic.h> 21*b961c48bSJyri Sarha #include <drm/drm_plane_helper.h> 22*b961c48bSJyri Sarha #include <drm/drm_atomic_helper.h> 23*b961c48bSJyri Sarha #include <uapi/drm/drm_fourcc.h> 24*b961c48bSJyri Sarha 25*b961c48bSJyri Sarha #include "tilcdc_drv.h" 26*b961c48bSJyri Sarha 27*b961c48bSJyri Sarha static const u32 tilcdc_formats[] = { DRM_FORMAT_RGB565, 28*b961c48bSJyri Sarha DRM_FORMAT_RGB888, 29*b961c48bSJyri Sarha DRM_FORMAT_XRGB8888 }; 30*b961c48bSJyri Sarha 31*b961c48bSJyri Sarha static struct drm_plane_funcs tilcdc_plane_funcs = { 32*b961c48bSJyri Sarha .update_plane = drm_atomic_helper_update_plane, 33*b961c48bSJyri Sarha .disable_plane = drm_atomic_helper_disable_plane, 34*b961c48bSJyri Sarha .destroy = drm_plane_cleanup, 35*b961c48bSJyri Sarha .set_property = drm_atomic_helper_plane_set_property, 36*b961c48bSJyri Sarha .reset = drm_atomic_helper_plane_reset, 37*b961c48bSJyri Sarha .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 38*b961c48bSJyri Sarha .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 39*b961c48bSJyri Sarha }; 40*b961c48bSJyri Sarha 41*b961c48bSJyri Sarha static int tilcdc_plane_atomic_check(struct drm_plane *plane, 42*b961c48bSJyri Sarha struct drm_plane_state *state) 43*b961c48bSJyri Sarha { 44*b961c48bSJyri Sarha struct drm_crtc_state *crtc_state; 45*b961c48bSJyri Sarha struct drm_plane_state *old_state = plane->state; 46*b961c48bSJyri Sarha unsigned int depth, bpp; 47*b961c48bSJyri Sarha 48*b961c48bSJyri Sarha if (!state->crtc) 49*b961c48bSJyri Sarha return 0; 50*b961c48bSJyri Sarha 51*b961c48bSJyri Sarha if (WARN_ON(!state->fb)) 52*b961c48bSJyri Sarha return -EINVAL; 53*b961c48bSJyri Sarha 54*b961c48bSJyri Sarha if (state->crtc_x || state->crtc_y) { 55*b961c48bSJyri Sarha dev_err(plane->dev->dev, "%s: crtc position must be zero.", 56*b961c48bSJyri Sarha __func__); 57*b961c48bSJyri Sarha return -EINVAL; 58*b961c48bSJyri Sarha } 59*b961c48bSJyri Sarha 60*b961c48bSJyri Sarha crtc_state = drm_atomic_get_existing_crtc_state(state->state, 61*b961c48bSJyri Sarha state->crtc); 62*b961c48bSJyri Sarha /* we should have a crtc state if the plane is attached to a crtc */ 63*b961c48bSJyri Sarha if (WARN_ON(!crtc_state)) 64*b961c48bSJyri Sarha return 0; 65*b961c48bSJyri Sarha 66*b961c48bSJyri Sarha if (crtc_state->mode.hdisplay != state->crtc_w || 67*b961c48bSJyri Sarha crtc_state->mode.vdisplay != state->crtc_h) { 68*b961c48bSJyri Sarha dev_err(plane->dev->dev, 69*b961c48bSJyri Sarha "%s: Size must match mode (%dx%d == %dx%d)", __func__, 70*b961c48bSJyri Sarha crtc_state->mode.hdisplay, crtc_state->mode.vdisplay, 71*b961c48bSJyri Sarha state->crtc_w, state->crtc_h); 72*b961c48bSJyri Sarha return -EINVAL; 73*b961c48bSJyri Sarha } 74*b961c48bSJyri Sarha 75*b961c48bSJyri Sarha drm_fb_get_bpp_depth(state->fb->pixel_format, &depth, &bpp); 76*b961c48bSJyri Sarha if (state->fb->pitches[0] != crtc_state->mode.hdisplay * bpp / 8) { 77*b961c48bSJyri Sarha dev_err(plane->dev->dev, 78*b961c48bSJyri Sarha "Invalid pitch: fb and crtc widths must be the same"); 79*b961c48bSJyri Sarha return -EINVAL; 80*b961c48bSJyri Sarha } 81*b961c48bSJyri Sarha 82*b961c48bSJyri Sarha if (state->fb && old_state->fb && 83*b961c48bSJyri Sarha state->fb->pixel_format != old_state->fb->pixel_format) { 84*b961c48bSJyri Sarha dev_dbg(plane->dev->dev, 85*b961c48bSJyri Sarha "%s(): pixel format change requires mode_change\n", 86*b961c48bSJyri Sarha __func__); 87*b961c48bSJyri Sarha crtc_state->mode_changed = true; 88*b961c48bSJyri Sarha } 89*b961c48bSJyri Sarha 90*b961c48bSJyri Sarha return 0; 91*b961c48bSJyri Sarha } 92*b961c48bSJyri Sarha 93*b961c48bSJyri Sarha static void tilcdc_plane_atomic_update(struct drm_plane *plane, 94*b961c48bSJyri Sarha struct drm_plane_state *old_state) 95*b961c48bSJyri Sarha { 96*b961c48bSJyri Sarha struct drm_plane_state *state = plane->state; 97*b961c48bSJyri Sarha 98*b961c48bSJyri Sarha if (!state->crtc) 99*b961c48bSJyri Sarha return; 100*b961c48bSJyri Sarha 101*b961c48bSJyri Sarha if (WARN_ON(!state->fb || !state->crtc->state)) 102*b961c48bSJyri Sarha return; 103*b961c48bSJyri Sarha 104*b961c48bSJyri Sarha tilcdc_crtc_page_flip(state->crtc, 105*b961c48bSJyri Sarha state->fb, 106*b961c48bSJyri Sarha state->crtc->state->event, 107*b961c48bSJyri Sarha 0); 108*b961c48bSJyri Sarha } 109*b961c48bSJyri Sarha 110*b961c48bSJyri Sarha static const struct drm_plane_helper_funcs plane_helper_funcs = { 111*b961c48bSJyri Sarha .atomic_check = tilcdc_plane_atomic_check, 112*b961c48bSJyri Sarha .atomic_update = tilcdc_plane_atomic_update, 113*b961c48bSJyri Sarha }; 114*b961c48bSJyri Sarha 115*b961c48bSJyri Sarha int tilcdc_plane_init(struct drm_device *dev, 116*b961c48bSJyri Sarha struct drm_plane *plane) 117*b961c48bSJyri Sarha { 118*b961c48bSJyri Sarha int ret; 119*b961c48bSJyri Sarha 120*b961c48bSJyri Sarha ret = drm_plane_init(dev, plane, 1, 121*b961c48bSJyri Sarha &tilcdc_plane_funcs, 122*b961c48bSJyri Sarha tilcdc_formats, 123*b961c48bSJyri Sarha ARRAY_SIZE(tilcdc_formats), 124*b961c48bSJyri Sarha true); 125*b961c48bSJyri Sarha if (ret) { 126*b961c48bSJyri Sarha dev_err(dev->dev, "Failed to initialize plane: %d\n", ret); 127*b961c48bSJyri Sarha return ret; 128*b961c48bSJyri Sarha } 129*b961c48bSJyri Sarha 130*b961c48bSJyri Sarha drm_plane_helper_add(plane, &plane_helper_funcs); 131*b961c48bSJyri Sarha 132*b961c48bSJyri Sarha return 0; 133*b961c48bSJyri Sarha } 134