/*
* Copyright (C) 2012 Russell King
* Rewritten from the dovefb driver, and Armada510 manuals.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_plane_helper.h>
#include "armada_crtc.h"
#include "armada_drm.h"
#include "armada_fb.h"
#include "armada_gem.h"
#include "armada_hw.h"
#include "armada_trace.h"
struct armada_frame_work {
struct armada_plane_work work;
struct drm_pending_vblank_event *event;
struct armada_regs regs[4];
struct drm_framebuffer *old_fb;
};
enum csc_mode {
CSC_AUTO = 0,
CSC_YUV_CCIR601 = 1,
CSC_YUV_CCIR709 = 2,
CSC_RGB_COMPUTER = 1,
CSC_RGB_STUDIO = 2,
};
static const uint32_t armada_primary_formats[] = {
DRM_FORMAT_UYVY,
DRM_FORMAT_YUYV,
DRM_FORMAT_VYUY,
DRM_FORMAT_YVYU,
DRM_FORMAT_ARGB8888,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_RGB888,
DRM_FORMAT_BGR888,
DRM_FORMAT_ARGB1555,
DRM_FORMAT_ABGR1555,
DRM_FORMAT_RGB565,
DRM_FORMAT_BGR565,
};
/*
* A note about interlacing. Let's consider HDMI 1920x1080i.
* The timing parameters we have from X are:
* Hact HsyA HsyI Htot Vact VsyA VsyI Vtot
* 1920 2448 2492 2640 1080 1084 1094 1125
* Which get translated to:
* Hact HsyA HsyI Htot Vact VsyA VsyI Vtot
* 1920 2448 2492 2640 540 542 547 562
*
* This is how it is defined by CEA-861-D - line and pixel numbers are
* referenced to the rising edge of VSYNC and HSYNC. Total clocks per
* line: 2640. The odd frame, the first active line is at line 21, and
* the even frame, the first active line is 584.
*
* LN: 560 561 562 563 567 568 569
* DE: ~~~|____________________________//__________________________
* HSYNC: ____|~|_____|~|_____|~|_____|~|_//__|~|_____|~|_____|~|_____
* VSYNC: _________________________|~~~~~~//~~~~~~~~~~~~~~~|__________
* 22 blanking lines. VSYNC at 1320 (referenced to the HSYNC rising edge).
*
* LN: 1123 1124 1125 1 5 6 7
* DE: ~~~|____________________________//__________________________
* HSYNC: ____|~|_____|~|_____|~|_____|~|_//__|~|_____|~|_____|~|_____
* VSYNC: ____________________|~~~~~~~~~~~//~~~~~~~~~~|_______________
* 23 blanking lines
*
* The Armada LCD Controller line and pixel numbers are, like X timings,
* referenced to the top left of the active frame.
*
* So, translating these to our LCD controller:
* Odd frame, 563 total lines, VSYNC at line 543-548, pixel 1128.
* Even frame, 562 total lines, VSYNC at line 542-547, pixel 2448.
* Note: Vsync front porch remains constant!
*
* if (odd_frame) {
* vtotal = mode->crtc_vtotal + 1;
* vbackporch = mode->crtc_vsync_start - mode->crtc_vdisplay + 1;
* vhorizpos = mode->crtc_hsync_start - mode->crtc_htotal / 2
* } else {
* vtotal = mode->crtc_vtotal;
* vbackporch = mode->crtc_vsync_start - mode->crtc_vdisplay;
* vhorizpos = mode->crtc_hsync_start;
* }
* vfrontporch = mode->crtc_vtotal - mode->crtc_vsync_end;
*
* So, we need to reprogram these registers on each vsync event:
* LCD_SPU_V_PORCH, LCD_SPU_ADV_REG, LCD_SPUT_V_H_TOTAL
*
* Note: we do not use the frame done interrupts because these appear
* to happen too early, and lead to jitter on the display (presumably
* they occur at the end of the last active line, before the vsync back
* porch, which we're reprogramming.)
*/
void
armada_drm_crtc_update_regs(