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