// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2011 Samsung Electronics Co.Ltd
* Authors:
* Seung-Woo Kim <sw0312.kim@samsung.com>
* Inki Dae <inki.dae@samsung.com>
* Joonyoung Shim <jy0922.shim@samsung.com>
*
* Based on drivers/media/video/s5p-tv/mixer_reg.c
*/
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/ktime.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <drm/drm_blend.h>
#include <drm/drm_edid.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_vblank.h>
#include <drm/exynos_drm.h>
#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_plane.h"
#include "regs-mixer.h"
#include "regs-vp.h"
#define MIXER_WIN_NR 3
#define VP_DEFAULT_WIN 2
/*
* Mixer color space conversion coefficient triplet.
* Used for CSC from RGB to YCbCr.
* Each coefficient is a 10-bit fixed point number with
* sign and no integer part, i.e.
* [0:8] = fractional part (representing a value y = x / 2^9)
* [9] = sign
* Negative values are encoded with two's complement.
*/
#define MXR_CSC_C(x) ((int)((x) * 512.0) & 0x3ff)
#define MXR_CSC_CT(a0, a1, a2) \
((MXR_CSC_C(a0) << 20) | (MXR_CSC_C(a1) << 10) | (MXR_CSC_C(a2) << 0))
/* YCbCr value, used for mixer background color configuration. */
#define MXR_YCBCR_VAL(y, cb, cr) (((y) << 16) | ((cb) << 8) | ((cr) << 0))
/* The pixelformats that are natively supported by the mixer. */
#define MXR_FORMAT_RGB565 4
#define MXR_FORMAT_ARGB1555 5
#define MXR_FORMAT_ARGB4444 6
#define MXR_FORMAT_ARGB8888 7
enum mixer_version_id {
MXR_VER_0_0_0_16,
MXR_VER_16_0_33_0,
MXR_VER_128_0_0_184,
};
enum mixer_flag_bits {
MXR_BIT_POWERED,
MXR_BIT_VSYNC,
MXR_BIT_INTERLACE,
MXR_BIT_VP_ENABLED,
MXR_BIT_HAS_SCLK,
};
static const uint32_t mixer_formats[] = {
DRM_FORMAT_XRGB4444,
DRM_FORMAT_ARGB4444,
DRM_FORMAT_XRGB1555,
DRM_FORMAT_ARGB1555,
DRM_FORMAT_RGB565,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_ARGB8888,
};
static const uint32_t vp_formats[] = {
DRM_FORMAT_NV12,
DRM_FORMAT_NV21,
};
struct mixer_context {
struct platform_device *pdev;
struct device *dev;
struct drm_device *drm_dev;
void *dma_priv;
struct exynos_drm_crtc *crtc;
struct exynos_drm_plane planes[MIXER_WIN_NR];
unsigned long flags;
int irq;
void __iomem *mixer_regs;
void __iomem *vp_regs;
spinlock_t reg_slock;
struct clk *mixer;
struct clk *vp;
struct clk *hdmi;
struct clk *sclk_mixer;
struct clk *sclk_hdmi;
struct clk *mout_mixer;
enum mixer_version_id mxr_ver;
int scan_value;
};
struct mixer_drv_data {
enum mixer_version_id version;
bool is_vp_enabled;
bool has_sclk;
};
static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
{
.zpos = 0,
.type = DRM_PLANE_TYPE_PRIMARY,
.pixel_formats = mixer_formats,
.num_pixel_formats =