tilcdc_crtc.c revision a9767188678725aac99d7990025dd5b822728ba8
116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark/* 216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * Copyright (C) 2012 Texas Instruments 316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * Author: Rob Clark <robdclark@gmail.com> 416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * 516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * This program is free software; you can redistribute it and/or modify it 616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * under the terms of the GNU General Public License version 2 as published by 716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * the Free Software Foundation. 816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * 916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * This program is distributed in the hope that it will be useful, but WITHOUT 1016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * more details. 1316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * 1416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * You should have received a copy of the GNU General Public License along with 1516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * this program. If not, see <http://www.gnu.org/licenses/>. 1616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark */ 1716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 1816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark#include <linux/kfifo.h> 1916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 2016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark#include "tilcdc_drv.h" 2116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark#include "tilcdc_regs.h" 2216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 2316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstruct tilcdc_crtc { 2416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_crtc base; 2516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 2616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark const struct tilcdc_panel_info *info; 2716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark uint32_t dirty; 2816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark dma_addr_t start, end; 2916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_pending_vblank_event *event; 3016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark int dpms; 3116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark wait_queue_head_t frame_done_wq; 3216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark bool frame_done; 3316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 3416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* fb currently set to scanout 0/1: */ 3516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_framebuffer *scanout[2]; 3616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 3716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* for deferred fb unref's: */ 3816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark DECLARE_KFIFO_PTR(unref_fifo, struct drm_framebuffer *); 3916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct work_struct work; 4016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark}; 4116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base) 4216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 4316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic void unref_worker(struct work_struct *work) 4416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 45f7b4575601dafb3cf3c568465ec6980de6d09b94Darren Etheridge struct tilcdc_crtc *tilcdc_crtc = 46f7b4575601dafb3cf3c568465ec6980de6d09b94Darren Etheridge container_of(work, struct tilcdc_crtc, work); 4716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_device *dev = tilcdc_crtc->base.dev; 4816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_framebuffer *fb; 4916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 5016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark mutex_lock(&dev->mode_config.mutex); 5116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark while (kfifo_get(&tilcdc_crtc->unref_fifo, &fb)) 5216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark drm_framebuffer_unreference(fb); 5316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark mutex_unlock(&dev->mode_config.mutex); 5416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 5516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 5616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic void set_scanout(struct drm_crtc *crtc, int n) 5716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 5816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark static const uint32_t base_reg[] = { 59f7b4575601dafb3cf3c568465ec6980de6d09b94Darren Etheridge LCDC_DMA_FB_BASE_ADDR_0_REG, 60f7b4575601dafb3cf3c568465ec6980de6d09b94Darren Etheridge LCDC_DMA_FB_BASE_ADDR_1_REG, 6116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark }; 6216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark static const uint32_t ceil_reg[] = { 63f7b4575601dafb3cf3c568465ec6980de6d09b94Darren Etheridge LCDC_DMA_FB_CEILING_ADDR_0_REG, 64f7b4575601dafb3cf3c568465ec6980de6d09b94Darren Etheridge LCDC_DMA_FB_CEILING_ADDR_1_REG, 6516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark }; 6616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark static const uint32_t stat[] = { 6716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark LCDC_END_OF_FRAME0, LCDC_END_OF_FRAME1, 6816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark }; 6916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 7016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_device *dev = crtc->dev; 7116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 7216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark pm_runtime_get_sync(dev->dev); 7316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_write(dev, base_reg[n], tilcdc_crtc->start); 7416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end); 7516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (tilcdc_crtc->scanout[n]) { 7616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (kfifo_put(&tilcdc_crtc->unref_fifo, 7716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark (const struct drm_framebuffer **)&tilcdc_crtc->scanout[n])) { 7816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_drm_private *priv = dev->dev_private; 7916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark queue_work(priv->wq, &tilcdc_crtc->work); 8016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } else { 8116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark dev_err(dev->dev, "unref fifo full!\n"); 8216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark drm_framebuffer_unreference(tilcdc_crtc->scanout[n]); 8316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 8416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 8516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->scanout[n] = crtc->fb; 8616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark drm_framebuffer_reference(tilcdc_crtc->scanout[n]); 8716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->dirty &= ~stat[n]; 8816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark pm_runtime_put_sync(dev->dev); 8916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 9016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 9116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic void update_scanout(struct drm_crtc *crtc) 9216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 9316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 9416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_device *dev = crtc->dev; 9516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_framebuffer *fb = crtc->fb; 9616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_gem_cma_object *gem; 9716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark unsigned int depth, bpp; 9816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 9916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp); 10016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark gem = drm_fb_cma_get_gem_obj(fb, 0); 10116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 10216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->start = gem->paddr + fb->offsets[0] + 10316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark (crtc->y * fb->pitches[0]) + (crtc->x * bpp/8); 10416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 10516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->end = tilcdc_crtc->start + 10616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark (crtc->mode.vdisplay * fb->pitches[0]); 10716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 10816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (tilcdc_crtc->dpms == DRM_MODE_DPMS_ON) { 10916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* already enabled, so just mark the frames that need 11016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * updating and they will be updated on vblank: 11116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark */ 11216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->dirty |= LCDC_END_OF_FRAME0 | LCDC_END_OF_FRAME1; 11316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark drm_vblank_get(dev, 0); 11416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } else { 11516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* not enabled yet, so update registers immediately: */ 11616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark set_scanout(crtc, 0); 11716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark set_scanout(crtc, 1); 11816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 11916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 12016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 12116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic void start(struct drm_crtc *crtc) 12216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 12316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_device *dev = crtc->dev; 12416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_drm_private *priv = dev->dev_private; 12516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 12616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (priv->rev == 2) { 12716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_set(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET); 12816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark msleep(1); 12916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_clear(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET); 13016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark msleep(1); 13116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 13216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 13316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_set(dev, LCDC_DMA_CTRL_REG, LCDC_DUAL_FRAME_BUFFER_ENABLE); 13416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_PALETTE_LOAD_MODE(DATA_ONLY)); 13516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); 13616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 13716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 13816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic void stop(struct drm_crtc *crtc) 13916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 14016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_device *dev = crtc->dev; 14116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 14216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); 14316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 14416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 14516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic void tilcdc_crtc_destroy(struct drm_crtc *crtc) 14616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 14716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 14816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 14916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON); 15016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 15116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark drm_crtc_cleanup(crtc); 15216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark WARN_ON(!kfifo_is_empty(&tilcdc_crtc->unref_fifo)); 15316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark kfifo_free(&tilcdc_crtc->unref_fifo); 15416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark kfree(tilcdc_crtc); 15516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 15616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 15716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic int tilcdc_crtc_page_flip(struct drm_crtc *crtc, 15816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_framebuffer *fb, 15916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_pending_vblank_event *event) 16016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 16116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 16216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_device *dev = crtc->dev; 16316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 16416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (tilcdc_crtc->event) { 16516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark dev_err(dev->dev, "already pending page flip!\n"); 16616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return -EBUSY; 16716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 16816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 16916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark crtc->fb = fb; 17016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->event = event; 17116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark update_scanout(crtc); 17216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 17316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return 0; 17416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 17516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 17616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode) 17716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 17816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 17916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_device *dev = crtc->dev; 18016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_drm_private *priv = dev->dev_private; 18116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 18216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* we really only care about on or off: */ 18316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (mode != DRM_MODE_DPMS_ON) 18416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark mode = DRM_MODE_DPMS_OFF; 18516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 18616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (tilcdc_crtc->dpms == mode) 18716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return; 18816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 18916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->dpms = mode; 19016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 19116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark pm_runtime_get_sync(dev->dev); 19216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 19316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (mode == DRM_MODE_DPMS_ON) { 19416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark pm_runtime_forbid(dev->dev); 19516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark start(crtc); 19616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } else { 19716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->frame_done = false; 19816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark stop(crtc); 19916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 200f7b4575601dafb3cf3c568465ec6980de6d09b94Darren Etheridge /* 201f7b4575601dafb3cf3c568465ec6980de6d09b94Darren Etheridge * if necessary wait for framedone irq which will still come 20216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * before putting things to sleep.. 20316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark */ 20416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (priv->rev == 2) { 20516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark int ret = wait_event_timeout( 20616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->frame_done_wq, 20716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->frame_done, 20816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark msecs_to_jiffies(50)); 20916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (ret == 0) 21016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark dev_err(dev->dev, "timeout waiting for framedone\n"); 21116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 21216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark pm_runtime_allow(dev->dev); 21316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 21416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 21516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark pm_runtime_put_sync(dev->dev); 21616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 21716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 21816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc, 21916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark const struct drm_display_mode *mode, 22016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_display_mode *adjusted_mode) 22116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 22216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return true; 22316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 22416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 22516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic void tilcdc_crtc_prepare(struct drm_crtc *crtc) 22616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 22716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 22816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 22916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 23016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic void tilcdc_crtc_commit(struct drm_crtc *crtc) 23116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 23216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 23316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 23416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 23516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic int tilcdc_crtc_mode_set(struct drm_crtc *crtc, 23616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_display_mode *mode, 23716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_display_mode *adjusted_mode, 23816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark int x, int y, 23916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_framebuffer *old_fb) 24016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 24116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 24216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_device *dev = crtc->dev; 24316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_drm_private *priv = dev->dev_private; 24416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark const struct tilcdc_panel_info *info = tilcdc_crtc->info; 24516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark uint32_t reg, hbp, hfp, hsw, vbp, vfp, vsw; 24616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark int ret; 24716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 24816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark ret = tilcdc_crtc_mode_valid(crtc, mode); 24916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (WARN_ON(ret)) 25016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return ret; 25116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 25216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (WARN_ON(!info)) 25316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return -EINVAL; 25416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 25516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark pm_runtime_get_sync(dev->dev); 25616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 25716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* Configure the Burst Size and fifo threshold of DMA: */ 25816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg = tilcdc_read(dev, LCDC_DMA_CTRL_REG) & ~0x00000770; 25916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark switch (info->dma_burst_sz) { 26016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark case 1: 26116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_1); 26216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark break; 26316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark case 2: 26416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_2); 26516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark break; 26616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark case 4: 26716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_4); 26816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark break; 26916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark case 8: 27016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_8); 27116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark break; 27216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark case 16: 27316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_16); 27416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark break; 27516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark default: 27616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return -EINVAL; 27716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 27816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg |= (info->fifo_th << 8); 27916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_write(dev, LCDC_DMA_CTRL_REG, reg); 28016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 28116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* Configure timings: */ 28216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark hbp = mode->htotal - mode->hsync_end; 28316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark hfp = mode->hsync_start - mode->hdisplay; 28416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark hsw = mode->hsync_end - mode->hsync_start; 28516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark vbp = mode->vtotal - mode->vsync_end; 28616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark vfp = mode->vsync_start - mode->vdisplay; 28716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark vsw = mode->vsync_end - mode->vsync_start; 28816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 28916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark DBG("%dx%d, hbp=%u, hfp=%u, hsw=%u, vbp=%u, vfp=%u, vsw=%u", 29016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark mode->hdisplay, mode->vdisplay, hbp, hfp, hsw, vbp, vfp, vsw); 29116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 29216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* Configure the AC Bias Period and Number of Transitions per Interrupt: */ 29316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00; 29416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) | 29516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt); 296db2b4bd09b43fc27ecd097e193f1135f5e40d347Darren Etheridge 297db2b4bd09b43fc27ecd097e193f1135f5e40d347Darren Etheridge /* 298db2b4bd09b43fc27ecd097e193f1135f5e40d347Darren Etheridge * subtract one from hfp, hbp, hsw because the hardware uses 299db2b4bd09b43fc27ecd097e193f1135f5e40d347Darren Etheridge * a value of 0 as 1 300db2b4bd09b43fc27ecd097e193f1135f5e40d347Darren Etheridge */ 30116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (priv->rev == 2) { 302c19b3e238d7573cbe0bb60f4578b7d1de4a13746Pantelis Antoniou /* clear bits we're going to set */ 303c19b3e238d7573cbe0bb60f4578b7d1de4a13746Pantelis Antoniou reg &= ~0x78000033; 304db2b4bd09b43fc27ecd097e193f1135f5e40d347Darren Etheridge reg |= ((hfp-1) & 0x300) >> 8; 305db2b4bd09b43fc27ecd097e193f1135f5e40d347Darren Etheridge reg |= ((hbp-1) & 0x300) >> 4; 306db2b4bd09b43fc27ecd097e193f1135f5e40d347Darren Etheridge reg |= ((hsw-1) & 0x3c0) << 21; 30716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 30816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg); 30916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 31016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg = (((mode->hdisplay >> 4) - 1) << 4) | 311db2b4bd09b43fc27ecd097e193f1135f5e40d347Darren Etheridge (((hbp-1) & 0xff) << 24) | 312db2b4bd09b43fc27ecd097e193f1135f5e40d347Darren Etheridge (((hfp-1) & 0xff) << 16) | 313db2b4bd09b43fc27ecd097e193f1135f5e40d347Darren Etheridge (((hsw-1) & 0x3f) << 10); 31416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (priv->rev == 2) 31516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3; 31616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg); 31716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 31816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg = ((mode->vdisplay - 1) & 0x3ff) | 31916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark ((vbp & 0xff) << 24) | 32016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark ((vfp & 0xff) << 16) | 321db2b4bd09b43fc27ecd097e193f1135f5e40d347Darren Etheridge (((vsw-1) & 0x3f) << 10); 32216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg); 32316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 3246bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge /* 3256bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge * be sure to set Bit 10 for the V2 LCDC controller, 3266bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge * otherwise limited to 1024 pixels width, stopping 3276bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge * 1920x1080 being suppoted. 3286bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge */ 3296bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge if (priv->rev == 2) { 3306bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge if ((mode->vdisplay - 1) & 0x400) { 3316bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, 3326bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge LCDC_LPP_B10); 3336bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge } else { 3346bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, 3356bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge LCDC_LPP_B10); 3366bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge } 3376bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge } 3386bf02c66b97379609a05bc715b96f874f2cefb33Darren Etheridge 33916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* Configure display type: */ 34016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) & 34116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE | 34216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark LCDC_V2_TFT_24BPP_MODE | LCDC_V2_TFT_24BPP_UNPACK | 0x000ff000); 34316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg |= LCDC_TFT_MODE; /* no monochrome/passive support */ 34416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (info->tft_alt_mode) 34516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg |= LCDC_TFT_ALT_ENABLE; 34616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (priv->rev == 2) { 34716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark unsigned int depth, bpp; 34816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 34916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark drm_fb_get_bpp_depth(crtc->fb->pixel_format, &depth, &bpp); 35016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark switch (bpp) { 35116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark case 16: 35216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark break; 35316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark case 32: 35416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg |= LCDC_V2_TFT_24BPP_UNPACK; 35516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* fallthrough */ 35616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark case 24: 35716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg |= LCDC_V2_TFT_24BPP_MODE; 35816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark break; 35916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark default: 36016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark dev_err(dev->dev, "invalid pixel format\n"); 36116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return -EINVAL; 36216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 36316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 36416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark reg |= info->fdd < 12; 36516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_write(dev, LCDC_RASTER_CTRL_REG, reg); 36616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 36716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (info->invert_pxl_clk) 36816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK); 36916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark else 37016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK); 37116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 37216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (info->sync_ctrl) 37316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL); 37416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark else 37516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL); 37616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 37716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (info->sync_edge) 37816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE); 37916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark else 38016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE); 38116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 382a9767188678725aac99d7990025dd5b822728ba8Darren Etheridge /* 383a9767188678725aac99d7990025dd5b822728ba8Darren Etheridge * use value from adjusted_mode here as this might have been 384a9767188678725aac99d7990025dd5b822728ba8Darren Etheridge * changed as part of the fixup for slave encoders to solve the 385a9767188678725aac99d7990025dd5b822728ba8Darren Etheridge * issue where tilcdc timings are not VESA compliant 386a9767188678725aac99d7990025dd5b822728ba8Darren Etheridge */ 387a9767188678725aac99d7990025dd5b822728ba8Darren Etheridge if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) 38816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); 38916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark else 39016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); 39116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 39216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (mode->flags & DRM_MODE_FLAG_NVSYNC) 39316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC); 39416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark else 39516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC); 39616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 39716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (info->raster_order) 39816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER); 39916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark else 40016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER); 40116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 40216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 40316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark update_scanout(crtc); 40416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc_update_clk(crtc); 40516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 40616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark pm_runtime_put_sync(dev->dev); 40716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 40816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return 0; 40916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 41016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 41116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic int tilcdc_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, 41216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_framebuffer *old_fb) 41316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 41416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark update_scanout(crtc); 41516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return 0; 41616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 41716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 41816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic const struct drm_crtc_funcs tilcdc_crtc_funcs = { 41916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark .destroy = tilcdc_crtc_destroy, 42016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark .set_config = drm_crtc_helper_set_config, 42116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark .page_flip = tilcdc_crtc_page_flip, 42216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark}; 42316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 42416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstatic const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = { 42516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark .dpms = tilcdc_crtc_dpms, 42616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark .mode_fixup = tilcdc_crtc_mode_fixup, 42716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark .prepare = tilcdc_crtc_prepare, 42816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark .commit = tilcdc_crtc_commit, 42916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark .mode_set = tilcdc_crtc_mode_set, 43016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark .mode_set_base = tilcdc_crtc_mode_set_base, 43116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark}; 43216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 43316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkint tilcdc_crtc_max_width(struct drm_crtc *crtc) 43416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 43516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_device *dev = crtc->dev; 43616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_drm_private *priv = dev->dev_private; 43716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark int max_width = 0; 43816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 43916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (priv->rev == 1) 44016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark max_width = 1024; 44116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark else if (priv->rev == 2) 44216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark max_width = 2048; 44316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 44416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return max_width; 44516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 44616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 44716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkint tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) 44816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 44916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_drm_private *priv = crtc->dev->dev_private; 45016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark unsigned int bandwidth; 451e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge uint32_t hbp, hfp, hsw, vbp, vfp, vsw; 45216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 453e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge /* 454e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge * check to see if the width is within the range that 455e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge * the LCD Controller physically supports 456e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge */ 45716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (mode->hdisplay > tilcdc_crtc_max_width(crtc)) 45816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return MODE_VIRTUAL_X; 45916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 46016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* width must be multiple of 16 */ 46116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (mode->hdisplay & 0xf) 46216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return MODE_VIRTUAL_X; 46316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 46416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (mode->vdisplay > 2048) 46516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return MODE_VIRTUAL_Y; 46616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 467e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge DBG("Processing mode %dx%d@%d with pixel clock %d", 468e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge mode->hdisplay, mode->vdisplay, 469e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge drm_mode_vrefresh(mode), mode->clock); 470e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge 471e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge hbp = mode->htotal - mode->hsync_end; 472e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge hfp = mode->hsync_start - mode->hdisplay; 473e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge hsw = mode->hsync_end - mode->hsync_start; 474e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge vbp = mode->vtotal - mode->vsync_end; 475e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge vfp = mode->vsync_start - mode->vdisplay; 476e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge vsw = mode->vsync_end - mode->vsync_start; 477e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge 478e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge if ((hbp-1) & ~0x3ff) { 479e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge DBG("Pruning mode: Horizontal Back Porch out of range"); 480e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge return MODE_HBLANK_WIDE; 481e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge } 482e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge 483e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge if ((hfp-1) & ~0x3ff) { 484e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge DBG("Pruning mode: Horizontal Front Porch out of range"); 485e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge return MODE_HBLANK_WIDE; 486e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge } 487e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge 488e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge if ((hsw-1) & ~0x3ff) { 489e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge DBG("Pruning mode: Horizontal Sync Width out of range"); 490e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge return MODE_HSYNC_WIDE; 491e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge } 492e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge 493e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge if (vbp & ~0xff) { 494e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge DBG("Pruning mode: Vertical Back Porch out of range"); 495e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge return MODE_VBLANK_WIDE; 496e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge } 497e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge 498e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge if (vfp & ~0xff) { 499e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge DBG("Pruning mode: Vertical Front Porch out of range"); 500e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge return MODE_VBLANK_WIDE; 501e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge } 502e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge 503e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge if ((vsw-1) & ~0x3f) { 504e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge DBG("Pruning mode: Vertical Sync Width out of range"); 505e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge return MODE_VSYNC_WIDE; 506e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge } 507e1c5d0a819e495a79cf76a8c63c5a30c327a89a5Darren Etheridge 5084e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge /* 5094e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge * some devices have a maximum allowed pixel clock 5104e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge * configured from the DT 5114e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge */ 5124e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge if (mode->clock > priv->max_pixelclock) { 513f7b4575601dafb3cf3c568465ec6980de6d09b94Darren Etheridge DBG("Pruning mode: pixel clock too high"); 5144e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge return MODE_CLOCK_HIGH; 5154e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge } 5164e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge 5174e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge /* 5184e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge * some devices further limit the max horizontal resolution 5194e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge * configured from the DT 5204e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge */ 5214e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge if (mode->hdisplay > priv->max_width) 5224e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge return MODE_BAD_WIDTH; 5234e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge 52416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* filter out modes that would require too much memory bandwidth: */ 5254e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge bandwidth = mode->hdisplay * mode->vdisplay * 5264e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge drm_mode_vrefresh(mode); 5274e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge if (bandwidth > priv->max_bandwidth) { 528f7b4575601dafb3cf3c568465ec6980de6d09b94Darren Etheridge DBG("Pruning mode: exceeds defined bandwidth limit"); 52916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return MODE_BAD; 5304e5643468715260209e42b715e8cd9643456d2bdDarren Etheridge } 53116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 53216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return MODE_OK; 53316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 53416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 53516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkvoid tilcdc_crtc_set_panel_info(struct drm_crtc *crtc, 53616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark const struct tilcdc_panel_info *info) 53716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 53816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 53916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->info = info; 54016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 54116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 54216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkvoid tilcdc_crtc_update_clk(struct drm_crtc *crtc) 54316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 54416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 54516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_device *dev = crtc->dev; 54616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_drm_private *priv = dev->dev_private; 54716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark int dpms = tilcdc_crtc->dpms; 54816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark unsigned int lcd_clk, div; 54916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark int ret; 55016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 55116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark pm_runtime_get_sync(dev->dev); 55216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 55316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (dpms == DRM_MODE_DPMS_ON) 55416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 55516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 55616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* in raster mode, minimum divisor is 2: */ 55716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark ret = clk_set_rate(priv->disp_clk, crtc->mode.clock * 1000 * 2); 55816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (ret) { 55916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark dev_err(dev->dev, "failed to set display clock rate to: %d\n", 56016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark crtc->mode.clock); 56116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark goto out; 56216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 56316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 56416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark lcd_clk = clk_get_rate(priv->clk); 56516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark div = lcd_clk / (crtc->mode.clock * 1000); 56616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 56716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark DBG("lcd_clk=%u, mode clock=%d, div=%u", lcd_clk, crtc->mode.clock, div); 56816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark DBG("fck=%lu, dpll_disp_ck=%lu", clk_get_rate(priv->clk), clk_get_rate(priv->disp_clk)); 56916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 57016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* Configure the LCD clock divisor. */ 57116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(div) | 57216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark LCDC_RASTER_MODE); 57316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 57416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (priv->rev == 2) 57516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_set(dev, LCDC_CLK_ENABLE_REG, 57616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN | 57716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark LCDC_V2_CORE_CLK_EN); 57816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 57916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (dpms == DRM_MODE_DPMS_ON) 58016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 58116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 58216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkout: 58316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark pm_runtime_put_sync(dev->dev); 58416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 58516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 58616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkirqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc) 58716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 58816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 58916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_device *dev = crtc->dev; 59016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_drm_private *priv = dev->dev_private; 59116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark uint32_t stat = tilcdc_read_irqstatus(dev); 59216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 59316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if ((stat & LCDC_SYNC_LOST) && (stat & LCDC_FIFO_UNDERFLOW)) { 59416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark stop(crtc); 59516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark dev_err(dev->dev, "error: %08x\n", stat); 59616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_clear_irqstatus(dev, stat); 59716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark start(crtc); 59816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } else if (stat & LCDC_PL_LOAD_DONE) { 59916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_clear_irqstatus(dev, stat); 60016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } else { 60116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_pending_vblank_event *event; 60216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark unsigned long flags; 60316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark uint32_t dirty = tilcdc_crtc->dirty & stat; 60416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 60516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_clear_irqstatus(dev, stat); 60616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 60716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (dirty & LCDC_END_OF_FRAME0) 60816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark set_scanout(crtc, 0); 60916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 61016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (dirty & LCDC_END_OF_FRAME1) 61116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark set_scanout(crtc, 1); 61216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 61316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark drm_handle_vblank(dev, 0); 61416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 61516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark spin_lock_irqsave(&dev->event_lock, flags); 61616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark event = tilcdc_crtc->event; 61716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->event = NULL; 61816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (event) 61916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark drm_send_vblank_event(dev, 0, event); 62016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark spin_unlock_irqrestore(&dev->event_lock, flags); 62116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 62216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (dirty && !tilcdc_crtc->dirty) 62316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark drm_vblank_put(dev, 0); 62416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 62516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 62616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (priv->rev == 2) { 62716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (stat & LCDC_FRAME_DONE) { 62816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->frame_done = true; 62916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark wake_up(&tilcdc_crtc->frame_done_wq); 63016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 63116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_write(dev, LCDC_END_OF_INT_IND_REG, 0); 63216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 63316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 63416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return IRQ_HANDLED; 63516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 63616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 63716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkvoid tilcdc_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) 63816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 63916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 64016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_pending_vblank_event *event; 64116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_device *dev = crtc->dev; 64216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark unsigned long flags; 64316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 64416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark /* Destroy the pending vertical blanking event associated with the 64516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark * pending page flip, if any, and disable vertical blanking interrupts. 64616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark */ 64716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark spin_lock_irqsave(&dev->event_lock, flags); 64816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark event = tilcdc_crtc->event; 64916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (event && event->base.file_priv == file) { 65016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->event = NULL; 65116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark event->base.destroy(&event->base); 65216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark drm_vblank_put(dev, 0); 65316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 65416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark spin_unlock_irqrestore(&dev->event_lock, flags); 65516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 65616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 65716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkstruct drm_crtc *tilcdc_crtc_create(struct drm_device *dev) 65816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark{ 65916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct tilcdc_crtc *tilcdc_crtc; 66016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark struct drm_crtc *crtc; 66116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark int ret; 66216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 66316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc = kzalloc(sizeof(*tilcdc_crtc), GFP_KERNEL); 66416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (!tilcdc_crtc) { 66516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark dev_err(dev->dev, "allocation failed\n"); 66616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return NULL; 66716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 66816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 66916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark crtc = &tilcdc_crtc->base; 67016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 67116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF; 67216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark init_waitqueue_head(&tilcdc_crtc->frame_done_wq); 67316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 67416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark ret = kfifo_alloc(&tilcdc_crtc->unref_fifo, 16, GFP_KERNEL); 67516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (ret) { 67616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark dev_err(dev->dev, "could not allocate unref FIFO\n"); 67716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark goto fail; 67816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark } 67916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 68016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark INIT_WORK(&tilcdc_crtc->work, unref_worker); 68116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 68216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs); 68316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark if (ret < 0) 68416ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark goto fail; 68516ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 68616ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark drm_crtc_helper_add(crtc, &tilcdc_crtc_helper_funcs); 68716ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 68816ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return crtc; 68916ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark 69016ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clarkfail: 69116ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark tilcdc_crtc_destroy(crtc); 69216ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark return NULL; 69316ea975eac671fa40a78594a116a44fef8e3f4a9Rob Clark} 694