Linux Audio

Check our new training course

Loading...
v4.6
   1/*
   2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
   3 * Authors:
   4 * Seung-Woo Kim <sw0312.kim@samsung.com>
   5 *	Inki Dae <inki.dae@samsung.com>
   6 *	Joonyoung Shim <jy0922.shim@samsung.com>
   7 *
   8 * Based on drivers/media/video/s5p-tv/mixer_reg.c
   9 *
  10 * This program is free software; you can redistribute  it and/or modify it
  11 * under  the terms of  the GNU General  Public License as published by the
  12 * Free Software Foundation;  either version 2 of the  License, or (at your
  13 * option) any later version.
  14 *
  15 */
  16
  17#include <drm/drmP.h>
  18
  19#include "regs-mixer.h"
  20#include "regs-vp.h"
  21
  22#include <linux/kernel.h>
  23#include <linux/spinlock.h>
  24#include <linux/wait.h>
  25#include <linux/i2c.h>
  26#include <linux/platform_device.h>
  27#include <linux/interrupt.h>
  28#include <linux/irq.h>
  29#include <linux/delay.h>
  30#include <linux/pm_runtime.h>
  31#include <linux/clk.h>
  32#include <linux/regulator/consumer.h>
  33#include <linux/of.h>
  34#include <linux/component.h>
  35
  36#include <drm/exynos_drm.h>
  37
  38#include "exynos_drm_drv.h"
  39#include "exynos_drm_crtc.h"
  40#include "exynos_drm_fb.h"
  41#include "exynos_drm_plane.h"
  42#include "exynos_drm_iommu.h"
 
 
 
  43
  44#define MIXER_WIN_NR		3
  45#define VP_DEFAULT_WIN		2
  46
  47/* The pixelformats that are natively supported by the mixer. */
  48#define MXR_FORMAT_RGB565	4
  49#define MXR_FORMAT_ARGB1555	5
  50#define MXR_FORMAT_ARGB4444	6
  51#define MXR_FORMAT_ARGB8888	7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  52
  53struct mixer_resources {
  54	int			irq;
  55	void __iomem		*mixer_regs;
  56	void __iomem		*vp_regs;
  57	spinlock_t		reg_slock;
  58	struct clk		*mixer;
  59	struct clk		*vp;
  60	struct clk		*hdmi;
  61	struct clk		*sclk_mixer;
  62	struct clk		*sclk_hdmi;
  63	struct clk		*mout_mixer;
  64};
  65
  66enum mixer_version_id {
  67	MXR_VER_0_0_0_16,
  68	MXR_VER_16_0_33_0,
  69	MXR_VER_128_0_0_184,
  70};
  71
  72enum mixer_flag_bits {
  73	MXR_BIT_POWERED,
  74	MXR_BIT_VSYNC,
  75};
  76
  77static const uint32_t mixer_formats[] = {
  78	DRM_FORMAT_XRGB4444,
  79	DRM_FORMAT_ARGB4444,
  80	DRM_FORMAT_XRGB1555,
  81	DRM_FORMAT_ARGB1555,
  82	DRM_FORMAT_RGB565,
  83	DRM_FORMAT_XRGB8888,
  84	DRM_FORMAT_ARGB8888,
  85};
  86
  87static const uint32_t vp_formats[] = {
  88	DRM_FORMAT_NV12,
  89	DRM_FORMAT_NV21,
  90};
  91
  92struct mixer_context {
  93	struct platform_device *pdev;
  94	struct device		*dev;
  95	struct drm_device	*drm_dev;
  96	struct exynos_drm_crtc	*crtc;
  97	struct exynos_drm_plane	planes[MIXER_WIN_NR];
  98	int			pipe;
  99	unsigned long		flags;
 100	bool			interlace;
 
 101	bool			vp_enabled;
 102	bool			has_sclk;
 103
 
 104	struct mixer_resources	mixer_res;
 
 105	enum mixer_version_id	mxr_ver;
 106	wait_queue_head_t	wait_vsync_queue;
 107	atomic_t		wait_vsync_event;
 108};
 109
 110struct mixer_drv_data {
 111	enum mixer_version_id	version;
 112	bool					is_vp_enabled;
 113	bool					has_sclk;
 114};
 115
 116static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
 117	{
 118		.zpos = 0,
 119		.type = DRM_PLANE_TYPE_PRIMARY,
 120		.pixel_formats = mixer_formats,
 121		.num_pixel_formats = ARRAY_SIZE(mixer_formats),
 122		.capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
 123				EXYNOS_DRM_PLANE_CAP_ZPOS,
 124	}, {
 125		.zpos = 1,
 126		.type = DRM_PLANE_TYPE_CURSOR,
 127		.pixel_formats = mixer_formats,
 128		.num_pixel_formats = ARRAY_SIZE(mixer_formats),
 129		.capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
 130				EXYNOS_DRM_PLANE_CAP_ZPOS,
 131	}, {
 132		.zpos = 2,
 133		.type = DRM_PLANE_TYPE_OVERLAY,
 134		.pixel_formats = vp_formats,
 135		.num_pixel_formats = ARRAY_SIZE(vp_formats),
 136		.capabilities = EXYNOS_DRM_PLANE_CAP_SCALE |
 137				EXYNOS_DRM_PLANE_CAP_ZPOS,
 138	},
 139};
 140
 141static const u8 filter_y_horiz_tap8[] = {
 142	0,	-1,	-1,	-1,	-1,	-1,	-1,	-1,
 143	-1,	-1,	-1,	-1,	-1,	0,	0,	0,
 144	0,	2,	4,	5,	6,	6,	6,	6,
 145	6,	5,	5,	4,	3,	2,	1,	1,
 146	0,	-6,	-12,	-16,	-18,	-20,	-21,	-20,
 147	-20,	-18,	-16,	-13,	-10,	-8,	-5,	-2,
 148	127,	126,	125,	121,	114,	107,	99,	89,
 149	79,	68,	57,	46,	35,	25,	16,	8,
 150};
 151
 152static const u8 filter_y_vert_tap4[] = {
 153	0,	-3,	-6,	-8,	-8,	-8,	-8,	-7,
 154	-6,	-5,	-4,	-3,	-2,	-1,	-1,	0,
 155	127,	126,	124,	118,	111,	102,	92,	81,
 156	70,	59,	48,	37,	27,	19,	11,	5,
 157	0,	5,	11,	19,	27,	37,	48,	59,
 158	70,	81,	92,	102,	111,	118,	124,	126,
 159	0,	0,	-1,	-1,	-2,	-3,	-4,	-5,
 160	-6,	-7,	-8,	-8,	-8,	-8,	-6,	-3,
 161};
 162
 163static const u8 filter_cr_horiz_tap4[] = {
 164	0,	-3,	-6,	-8,	-8,	-8,	-8,	-7,
 165	-6,	-5,	-4,	-3,	-2,	-1,	-1,	0,
 166	127,	126,	124,	118,	111,	102,	92,	81,
 167	70,	59,	48,	37,	27,	19,	11,	5,
 168};
 169
 170static inline bool is_alpha_format(unsigned int pixel_format)
 171{
 172	switch (pixel_format) {
 173	case DRM_FORMAT_ARGB8888:
 174	case DRM_FORMAT_ARGB1555:
 175	case DRM_FORMAT_ARGB4444:
 176		return true;
 177	default:
 178		return false;
 179	}
 180}
 181
 182static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
 183{
 184	return readl(res->vp_regs + reg_id);
 185}
 186
 187static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
 188				 u32 val)
 189{
 190	writel(val, res->vp_regs + reg_id);
 191}
 192
 193static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
 194				 u32 val, u32 mask)
 195{
 196	u32 old = vp_reg_read(res, reg_id);
 197
 198	val = (val & mask) | (old & ~mask);
 199	writel(val, res->vp_regs + reg_id);
 200}
 201
 202static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
 203{
 204	return readl(res->mixer_regs + reg_id);
 205}
 206
 207static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
 208				 u32 val)
 209{
 210	writel(val, res->mixer_regs + reg_id);
 211}
 212
 213static inline void mixer_reg_writemask(struct mixer_resources *res,
 214				 u32 reg_id, u32 val, u32 mask)
 215{
 216	u32 old = mixer_reg_read(res, reg_id);
 217
 218	val = (val & mask) | (old & ~mask);
 219	writel(val, res->mixer_regs + reg_id);
 220}
 221
 222static void mixer_regs_dump(struct mixer_context *ctx)
 223{
 224#define DUMPREG(reg_id) \
 225do { \
 226	DRM_DEBUG_KMS(#reg_id " = %08x\n", \
 227		(u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
 228} while (0)
 229
 230	DUMPREG(MXR_STATUS);
 231	DUMPREG(MXR_CFG);
 232	DUMPREG(MXR_INT_EN);
 233	DUMPREG(MXR_INT_STATUS);
 234
 235	DUMPREG(MXR_LAYER_CFG);
 236	DUMPREG(MXR_VIDEO_CFG);
 237
 238	DUMPREG(MXR_GRAPHIC0_CFG);
 239	DUMPREG(MXR_GRAPHIC0_BASE);
 240	DUMPREG(MXR_GRAPHIC0_SPAN);
 241	DUMPREG(MXR_GRAPHIC0_WH);
 242	DUMPREG(MXR_GRAPHIC0_SXY);
 243	DUMPREG(MXR_GRAPHIC0_DXY);
 244
 245	DUMPREG(MXR_GRAPHIC1_CFG);
 246	DUMPREG(MXR_GRAPHIC1_BASE);
 247	DUMPREG(MXR_GRAPHIC1_SPAN);
 248	DUMPREG(MXR_GRAPHIC1_WH);
 249	DUMPREG(MXR_GRAPHIC1_SXY);
 250	DUMPREG(MXR_GRAPHIC1_DXY);
 251#undef DUMPREG
 252}
 253
 254static void vp_regs_dump(struct mixer_context *ctx)
 255{
 256#define DUMPREG(reg_id) \
 257do { \
 258	DRM_DEBUG_KMS(#reg_id " = %08x\n", \
 259		(u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
 260} while (0)
 261
 262	DUMPREG(VP_ENABLE);
 263	DUMPREG(VP_SRESET);
 264	DUMPREG(VP_SHADOW_UPDATE);
 265	DUMPREG(VP_FIELD_ID);
 266	DUMPREG(VP_MODE);
 267	DUMPREG(VP_IMG_SIZE_Y);
 268	DUMPREG(VP_IMG_SIZE_C);
 269	DUMPREG(VP_PER_RATE_CTRL);
 270	DUMPREG(VP_TOP_Y_PTR);
 271	DUMPREG(VP_BOT_Y_PTR);
 272	DUMPREG(VP_TOP_C_PTR);
 273	DUMPREG(VP_BOT_C_PTR);
 274	DUMPREG(VP_ENDIAN_MODE);
 275	DUMPREG(VP_SRC_H_POSITION);
 276	DUMPREG(VP_SRC_V_POSITION);
 277	DUMPREG(VP_SRC_WIDTH);
 278	DUMPREG(VP_SRC_HEIGHT);
 279	DUMPREG(VP_DST_H_POSITION);
 280	DUMPREG(VP_DST_V_POSITION);
 281	DUMPREG(VP_DST_WIDTH);
 282	DUMPREG(VP_DST_HEIGHT);
 283	DUMPREG(VP_H_RATIO);
 284	DUMPREG(VP_V_RATIO);
 285
 286#undef DUMPREG
 287}
 288
 289static inline void vp_filter_set(struct mixer_resources *res,
 290		int reg_id, const u8 *data, unsigned int size)
 291{
 292	/* assure 4-byte align */
 293	BUG_ON(size & 3);
 294	for (; size; size -= 4, reg_id += 4, data += 4) {
 295		u32 val = (data[0] << 24) |  (data[1] << 16) |
 296			(data[2] << 8) | data[3];
 297		vp_reg_write(res, reg_id, val);
 298	}
 299}
 300
 301static void vp_default_filter(struct mixer_resources *res)
 302{
 303	vp_filter_set(res, VP_POLY8_Y0_LL,
 304		filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
 305	vp_filter_set(res, VP_POLY4_Y0_LL,
 306		filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
 307	vp_filter_set(res, VP_POLY4_C0_LL,
 308		filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
 309}
 310
 311static void mixer_cfg_gfx_blend(struct mixer_context *ctx, unsigned int win,
 312				bool alpha)
 313{
 314	struct mixer_resources *res = &ctx->mixer_res;
 315	u32 val;
 316
 317	val  = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
 318	if (alpha) {
 319		/* blending based on pixel alpha */
 320		val |= MXR_GRP_CFG_BLEND_PRE_MUL;
 321		val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
 322	}
 323	mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
 324			    val, MXR_GRP_CFG_MISC_MASK);
 325}
 326
 327static void mixer_cfg_vp_blend(struct mixer_context *ctx)
 328{
 329	struct mixer_resources *res = &ctx->mixer_res;
 330	u32 val;
 331
 332	/*
 333	 * No blending at the moment since the NV12/NV21 pixelformats don't
 334	 * have an alpha channel. However the mixer supports a global alpha
 335	 * value for a layer. Once this functionality is exposed, we can
 336	 * support blending of the video layer through this.
 337	 */
 338	val = 0;
 339	mixer_reg_write(res, MXR_VIDEO_CFG, val);
 340}
 341
 342static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
 343{
 344	struct mixer_resources *res = &ctx->mixer_res;
 345
 346	/* block update on vsync */
 347	mixer_reg_writemask(res, MXR_STATUS, enable ?
 348			MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
 349
 350	if (ctx->vp_enabled)
 351		vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
 352			VP_SHADOW_UPDATE_ENABLE : 0);
 353}
 354
 355static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
 356{
 357	struct mixer_resources *res = &ctx->mixer_res;
 358	u32 val;
 359
 360	/* choosing between interlace and progressive mode */
 361	val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
 362				MXR_CFG_SCAN_PROGRESSIVE);
 363
 364	if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
 365		/* choosing between proper HD and SD mode */
 366		if (height <= 480)
 367			val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
 368		else if (height <= 576)
 369			val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
 370		else if (height <= 720)
 371			val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
 372		else if (height <= 1080)
 373			val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
 374		else
 375			val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
 376	}
 377
 378	mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
 379}
 380
 381static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
 382{
 383	struct mixer_resources *res = &ctx->mixer_res;
 384	u32 val;
 385
 386	if (height == 480) {
 387		val = MXR_CFG_RGB601_0_255;
 388	} else if (height == 576) {
 389		val = MXR_CFG_RGB601_0_255;
 390	} else if (height == 720) {
 391		val = MXR_CFG_RGB709_16_235;
 392		mixer_reg_write(res, MXR_CM_COEFF_Y,
 393				(1 << 30) | (94 << 20) | (314 << 10) |
 394				(32 << 0));
 395		mixer_reg_write(res, MXR_CM_COEFF_CB,
 396				(972 << 20) | (851 << 10) | (225 << 0));
 397		mixer_reg_write(res, MXR_CM_COEFF_CR,
 398				(225 << 20) | (820 << 10) | (1004 << 0));
 399	} else if (height == 1080) {
 400		val = MXR_CFG_RGB709_16_235;
 401		mixer_reg_write(res, MXR_CM_COEFF_Y,
 402				(1 << 30) | (94 << 20) | (314 << 10) |
 403				(32 << 0));
 404		mixer_reg_write(res, MXR_CM_COEFF_CB,
 405				(972 << 20) | (851 << 10) | (225 << 0));
 406		mixer_reg_write(res, MXR_CM_COEFF_CR,
 407				(225 << 20) | (820 << 10) | (1004 << 0));
 408	} else {
 409		val = MXR_CFG_RGB709_16_235;
 410		mixer_reg_write(res, MXR_CM_COEFF_Y,
 411				(1 << 30) | (94 << 20) | (314 << 10) |
 412				(32 << 0));
 413		mixer_reg_write(res, MXR_CM_COEFF_CB,
 414				(972 << 20) | (851 << 10) | (225 << 0));
 415		mixer_reg_write(res, MXR_CM_COEFF_CR,
 416				(225 << 20) | (820 << 10) | (1004 << 0));
 417	}
 418
 419	mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
 420}
 421
 422static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win,
 423			    unsigned int priority, bool enable)
 424{
 425	struct mixer_resources *res = &ctx->mixer_res;
 426	u32 val = enable ? ~0 : 0;
 427
 428	switch (win) {
 429	case 0:
 430		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
 431		mixer_reg_writemask(res, MXR_LAYER_CFG,
 432				    MXR_LAYER_CFG_GRP0_VAL(priority),
 433				    MXR_LAYER_CFG_GRP0_MASK);
 434		break;
 435	case 1:
 436		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
 437		mixer_reg_writemask(res, MXR_LAYER_CFG,
 438				    MXR_LAYER_CFG_GRP1_VAL(priority),
 439				    MXR_LAYER_CFG_GRP1_MASK);
 440		break;
 441	case VP_DEFAULT_WIN:
 442		if (ctx->vp_enabled) {
 443			vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
 444			mixer_reg_writemask(res, MXR_CFG, val,
 445				MXR_CFG_VP_ENABLE);
 446			mixer_reg_writemask(res, MXR_LAYER_CFG,
 447					    MXR_LAYER_CFG_VP_VAL(priority),
 448					    MXR_LAYER_CFG_VP_MASK);
 449		}
 450		break;
 451	}
 452}
 453
 454static void mixer_run(struct mixer_context *ctx)
 455{
 456	struct mixer_resources *res = &ctx->mixer_res;
 457
 458	mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
 459}
 460
 461static void mixer_stop(struct mixer_context *ctx)
 462{
 463	struct mixer_resources *res = &ctx->mixer_res;
 464	int timeout = 20;
 465
 466	mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
 467
 468	while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
 469			--timeout)
 470		usleep_range(10000, 12000);
 471}
 472
 473static void vp_video_buffer(struct mixer_context *ctx,
 474			    struct exynos_drm_plane *plane)
 475{
 476	struct exynos_drm_plane_state *state =
 477				to_exynos_plane_state(plane->base.state);
 478	struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode;
 479	struct mixer_resources *res = &ctx->mixer_res;
 480	struct drm_framebuffer *fb = state->base.fb;
 481	unsigned long flags;
 
 
 
 482	dma_addr_t luma_addr[2], chroma_addr[2];
 483	bool tiled_mode = false;
 484	bool crcb_mode = false;
 485	u32 val;
 486
 487	switch (fb->pixel_format) {
 
 
 
 
 488	case DRM_FORMAT_NV12:
 489		crcb_mode = false;
 
 490		break;
 491	case DRM_FORMAT_NV21:
 492		crcb_mode = true;
 493		break;
 494	default:
 
 
 
 
 495		DRM_ERROR("pixel format for vp is wrong [%d].\n",
 496				fb->pixel_format);
 497		return;
 498	}
 499
 500	luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
 501	chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
 
 
 
 
 
 
 
 
 
 
 502
 503	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
 504		ctx->interlace = true;
 505		if (tiled_mode) {
 506			luma_addr[1] = luma_addr[0] + 0x40;
 507			chroma_addr[1] = chroma_addr[0] + 0x40;
 508		} else {
 509			luma_addr[1] = luma_addr[0] + fb->pitches[0];
 510			chroma_addr[1] = chroma_addr[0] + fb->pitches[0];
 511		}
 512	} else {
 513		ctx->interlace = false;
 514		luma_addr[1] = 0;
 515		chroma_addr[1] = 0;
 516	}
 517
 518	spin_lock_irqsave(&res->reg_slock, flags);
 
 519
 520	/* interlace or progressive scan mode */
 521	val = (ctx->interlace ? ~0 : 0);
 522	vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
 523
 524	/* setup format */
 525	val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
 526	val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
 527	vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
 528
 529	/* setting size of input image */
 530	vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) |
 531		VP_IMG_VSIZE(fb->height));
 532	/* chroma height has to reduced by 2 to avoid chroma distorions */
 533	vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) |
 534		VP_IMG_VSIZE(fb->height / 2));
 535
 536	vp_reg_write(res, VP_SRC_WIDTH, state->src.w);
 537	vp_reg_write(res, VP_SRC_HEIGHT, state->src.h);
 538	vp_reg_write(res, VP_SRC_H_POSITION,
 539			VP_SRC_H_POSITION_VAL(state->src.x));
 540	vp_reg_write(res, VP_SRC_V_POSITION, state->src.y);
 541
 542	vp_reg_write(res, VP_DST_WIDTH, state->crtc.w);
 543	vp_reg_write(res, VP_DST_H_POSITION, state->crtc.x);
 544	if (ctx->interlace) {
 545		vp_reg_write(res, VP_DST_HEIGHT, state->crtc.h / 2);
 546		vp_reg_write(res, VP_DST_V_POSITION, state->crtc.y / 2);
 547	} else {
 548		vp_reg_write(res, VP_DST_HEIGHT, state->crtc.h);
 549		vp_reg_write(res, VP_DST_V_POSITION, state->crtc.y);
 550	}
 551
 552	vp_reg_write(res, VP_H_RATIO, state->h_ratio);
 553	vp_reg_write(res, VP_V_RATIO, state->v_ratio);
 554
 555	vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
 556
 557	/* set buffer address to vp */
 558	vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
 559	vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
 560	vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
 561	vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
 562
 563	mixer_cfg_scan(ctx, mode->vdisplay);
 564	mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
 565	mixer_cfg_layer(ctx, plane->index, state->zpos + 1, true);
 566	mixer_cfg_vp_blend(ctx);
 567	mixer_run(ctx);
 568
 
 569	spin_unlock_irqrestore(&res->reg_slock, flags);
 570
 571	mixer_regs_dump(ctx);
 572	vp_regs_dump(ctx);
 573}
 574
 575static void mixer_layer_update(struct mixer_context *ctx)
 576{
 577	struct mixer_resources *res = &ctx->mixer_res;
 
 
 
 578
 579	mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
 
 
 580}
 581
 582static void mixer_graph_buffer(struct mixer_context *ctx,
 583			       struct exynos_drm_plane *plane)
 584{
 585	struct exynos_drm_plane_state *state =
 586				to_exynos_plane_state(plane->base.state);
 587	struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode;
 588	struct mixer_resources *res = &ctx->mixer_res;
 589	struct drm_framebuffer *fb = state->base.fb;
 590	unsigned long flags;
 591	unsigned int win = plane->index;
 592	unsigned int x_ratio = 0, y_ratio = 0;
 593	unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
 594	dma_addr_t dma_addr;
 595	unsigned int fmt;
 596	u32 val;
 597
 598	switch (fb->pixel_format) {
 599	case DRM_FORMAT_XRGB4444:
 600	case DRM_FORMAT_ARGB4444:
 601		fmt = MXR_FORMAT_ARGB4444;
 602		break;
 603
 604	case DRM_FORMAT_XRGB1555:
 605	case DRM_FORMAT_ARGB1555:
 606		fmt = MXR_FORMAT_ARGB1555;
 
 
 
 
 
 607		break;
 608
 609	case DRM_FORMAT_RGB565:
 610		fmt = MXR_FORMAT_RGB565;
 611		break;
 612
 613	case DRM_FORMAT_XRGB8888:
 614	case DRM_FORMAT_ARGB8888:
 615		fmt = MXR_FORMAT_ARGB8888;
 616		break;
 617
 618	default:
 619		DRM_DEBUG_KMS("pixelformat unsupported by mixer\n");
 620		return;
 621	}
 622
 623	/* ratio is already checked by common plane code */
 624	x_ratio = state->h_ratio == (1 << 15);
 625	y_ratio = state->v_ratio == (1 << 15);
 626
 627	dst_x_offset = state->crtc.x;
 628	dst_y_offset = state->crtc.y;
 629
 630	/* converting dma address base and source offset */
 631	dma_addr = exynos_drm_fb_dma_addr(fb, 0)
 632		+ (state->src.x * fb->bits_per_pixel >> 3)
 633		+ (state->src.y * fb->pitches[0]);
 634	src_x_offset = 0;
 635	src_y_offset = 0;
 636
 637	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 638		ctx->interlace = true;
 639	else
 640		ctx->interlace = false;
 641
 642	spin_lock_irqsave(&res->reg_slock, flags);
 
 643
 644	/* setup format */
 645	mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
 646		MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
 647
 648	/* setup geometry */
 649	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win),
 650			fb->pitches[0] / (fb->bits_per_pixel >> 3));
 651
 652	/* setup display size */
 653	if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
 654		win == DEFAULT_WIN) {
 655		val  = MXR_MXR_RES_HEIGHT(mode->vdisplay);
 656		val |= MXR_MXR_RES_WIDTH(mode->hdisplay);
 657		mixer_reg_write(res, MXR_RESOLUTION, val);
 658	}
 659
 660	val  = MXR_GRP_WH_WIDTH(state->src.w);
 661	val |= MXR_GRP_WH_HEIGHT(state->src.h);
 662	val |= MXR_GRP_WH_H_SCALE(x_ratio);
 663	val |= MXR_GRP_WH_V_SCALE(y_ratio);
 664	mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
 665
 666	/* setup offsets in source image */
 667	val  = MXR_GRP_SXY_SX(src_x_offset);
 668	val |= MXR_GRP_SXY_SY(src_y_offset);
 669	mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
 670
 671	/* setup offsets in display image */
 672	val  = MXR_GRP_DXY_DX(dst_x_offset);
 673	val |= MXR_GRP_DXY_DY(dst_y_offset);
 674	mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
 675
 676	/* set buffer address to mixer */
 677	mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
 678
 679	mixer_cfg_scan(ctx, mode->vdisplay);
 680	mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
 681	mixer_cfg_layer(ctx, win, state->zpos + 1, true);
 682	mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->pixel_format));
 683
 684	/* layer update mandatory for mixer 16.0.33.0 */
 685	if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
 686		ctx->mxr_ver == MXR_VER_128_0_0_184)
 687		mixer_layer_update(ctx);
 688
 689	mixer_run(ctx);
 690
 
 691	spin_unlock_irqrestore(&res->reg_slock, flags);
 692
 693	mixer_regs_dump(ctx);
 694}
 695
 696static void vp_win_reset(struct mixer_context *ctx)
 697{
 698	struct mixer_resources *res = &ctx->mixer_res;
 699	int tries = 100;
 700
 701	vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
 702	for (tries = 100; tries; --tries) {
 703		/* waiting until VP_SRESET_PROCESSING is 0 */
 704		if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
 705			break;
 706		mdelay(10);
 707	}
 708	WARN(tries == 0, "failed to reset Video Processor\n");
 709}
 710
 711static void mixer_win_reset(struct mixer_context *ctx)
 712{
 713	struct mixer_resources *res = &ctx->mixer_res;
 714	unsigned long flags;
 
 715
 716	spin_lock_irqsave(&res->reg_slock, flags);
 
 717
 718	mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
 719
 720	/* set output in RGB888 mode */
 721	mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
 722
 723	/* 16 beat burst in DMA */
 724	mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
 725		MXR_STATUS_BURST_MASK);
 726
 727	/* reset default layer priority */
 728	mixer_reg_write(res, MXR_LAYER_CFG, 0);
 
 
 
 
 
 
 
 
 
 729
 730	/* setting background color */
 731	mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
 732	mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
 733	mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
 734
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 735	if (ctx->vp_enabled) {
 736		/* configuration of Video Processor Registers */
 737		vp_win_reset(ctx);
 738		vp_default_filter(res);
 739	}
 740
 741	/* disable all layers */
 742	mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
 743	mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
 744	if (ctx->vp_enabled)
 745		mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
 746
 
 747	spin_unlock_irqrestore(&res->reg_slock, flags);
 748}
 749
 750static irqreturn_t mixer_irq_handler(int irq, void *arg)
 751{
 752	struct mixer_context *ctx = arg;
 753	struct mixer_resources *res = &ctx->mixer_res;
 754	u32 val, base, shadow;
 755	int win;
 756
 757	spin_lock(&res->reg_slock);
 758
 759	/* read interrupt status for handling and clearing flags for VSYNC */
 760	val = mixer_reg_read(res, MXR_INT_STATUS);
 761
 762	/* handling VSYNC */
 763	if (val & MXR_INT_STATUS_VSYNC) {
 764		/* vsync interrupt use different bit for read and clear */
 765		val |= MXR_INT_CLEAR_VSYNC;
 766		val &= ~MXR_INT_STATUS_VSYNC;
 767
 768		/* interlace scan need to check shadow register */
 769		if (ctx->interlace) {
 770			base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
 771			shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
 772			if (base != shadow)
 773				goto out;
 774
 775			base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
 776			shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
 777			if (base != shadow)
 778				goto out;
 779		}
 780
 781		drm_crtc_handle_vblank(&ctx->crtc->base);
 782		for (win = 0 ; win < MIXER_WIN_NR ; win++) {
 783			struct exynos_drm_plane *plane = &ctx->planes[win];
 784
 785			if (!plane->pending_fb)
 786				continue;
 787
 788			exynos_drm_crtc_finish_update(ctx->crtc, plane);
 789		}
 790
 791		/* set wait vsync event to zero and wake up queue. */
 792		if (atomic_read(&ctx->wait_vsync_event)) {
 793			atomic_set(&ctx->wait_vsync_event, 0);
 794			wake_up(&ctx->wait_vsync_queue);
 795		}
 796	}
 797
 798out:
 799	/* clear interrupts */
 
 
 
 
 
 800	mixer_reg_write(res, MXR_INT_STATUS, val);
 801
 802	spin_unlock(&res->reg_slock);
 803
 804	return IRQ_HANDLED;
 805}
 806
 807static int mixer_resources_init(struct mixer_context *mixer_ctx)
 808{
 809	struct device *dev = &mixer_ctx->pdev->dev;
 810	struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
 811	struct resource *res;
 812	int ret;
 813
 814	spin_lock_init(&mixer_res->reg_slock);
 815
 816	mixer_res->mixer = devm_clk_get(dev, "mixer");
 817	if (IS_ERR(mixer_res->mixer)) {
 818		dev_err(dev, "failed to get clock 'mixer'\n");
 819		return -ENODEV;
 820	}
 821
 822	mixer_res->hdmi = devm_clk_get(dev, "hdmi");
 823	if (IS_ERR(mixer_res->hdmi)) {
 824		dev_err(dev, "failed to get clock 'hdmi'\n");
 825		return PTR_ERR(mixer_res->hdmi);
 826	}
 827
 828	mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
 829	if (IS_ERR(mixer_res->sclk_hdmi)) {
 830		dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
 831		return -ENODEV;
 832	}
 833	res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
 834	if (res == NULL) {
 835		dev_err(dev, "get memory resource failed.\n");
 836		return -ENXIO;
 837	}
 838
 839	mixer_res->mixer_regs = devm_ioremap(dev, res->start,
 840							resource_size(res));
 841	if (mixer_res->mixer_regs == NULL) {
 842		dev_err(dev, "register mapping failed.\n");
 843		return -ENXIO;
 844	}
 845
 846	res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
 847	if (res == NULL) {
 848		dev_err(dev, "get interrupt resource failed.\n");
 849		return -ENXIO;
 850	}
 851
 852	ret = devm_request_irq(dev, res->start, mixer_irq_handler,
 853						0, "drm_mixer", mixer_ctx);
 854	if (ret) {
 855		dev_err(dev, "request interrupt failed.\n");
 856		return ret;
 857	}
 858	mixer_res->irq = res->start;
 859
 860	return 0;
 861}
 862
 863static int vp_resources_init(struct mixer_context *mixer_ctx)
 864{
 865	struct device *dev = &mixer_ctx->pdev->dev;
 866	struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
 867	struct resource *res;
 868
 869	mixer_res->vp = devm_clk_get(dev, "vp");
 870	if (IS_ERR(mixer_res->vp)) {
 871		dev_err(dev, "failed to get clock 'vp'\n");
 872		return -ENODEV;
 873	}
 874
 875	if (mixer_ctx->has_sclk) {
 876		mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
 877		if (IS_ERR(mixer_res->sclk_mixer)) {
 878			dev_err(dev, "failed to get clock 'sclk_mixer'\n");
 879			return -ENODEV;
 880		}
 881		mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
 882		if (IS_ERR(mixer_res->mout_mixer)) {
 883			dev_err(dev, "failed to get clock 'mout_mixer'\n");
 884			return -ENODEV;
 885		}
 886
 887		if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
 888			clk_set_parent(mixer_res->mout_mixer,
 889				       mixer_res->sclk_hdmi);
 890	}
 891
 
 
 
 892	res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
 893	if (res == NULL) {
 894		dev_err(dev, "get memory resource failed.\n");
 895		return -ENXIO;
 896	}
 897
 898	mixer_res->vp_regs = devm_ioremap(dev, res->start,
 899							resource_size(res));
 900	if (mixer_res->vp_regs == NULL) {
 901		dev_err(dev, "register mapping failed.\n");
 902		return -ENXIO;
 903	}
 904
 905	return 0;
 906}
 907
 908static int mixer_initialize(struct mixer_context *mixer_ctx,
 909			struct drm_device *drm_dev)
 910{
 911	int ret;
 912	struct exynos_drm_private *priv;
 913	priv = drm_dev->dev_private;
 914
 915	mixer_ctx->drm_dev = drm_dev;
 916	mixer_ctx->pipe = priv->pipe++;
 917
 918	/* acquire resources: regs, irqs, clocks */
 919	ret = mixer_resources_init(mixer_ctx);
 920	if (ret) {
 921		DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
 922		return ret;
 923	}
 924
 925	if (mixer_ctx->vp_enabled) {
 926		/* acquire vp resources: regs, irqs, clocks */
 927		ret = vp_resources_init(mixer_ctx);
 928		if (ret) {
 929			DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
 930			return ret;
 931		}
 932	}
 933
 934	ret = drm_iommu_attach_device(drm_dev, mixer_ctx->dev);
 935	if (ret)
 936		priv->pipe--;
 937
 938	return ret;
 939}
 940
 941static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
 942{
 943	drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
 
 
 
 944}
 945
 946static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
 947{
 948	struct mixer_context *mixer_ctx = crtc->ctx;
 949	struct mixer_resources *res = &mixer_ctx->mixer_res;
 950
 951	__set_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
 952	if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
 953		return 0;
 
 954
 955	/* enable vsync interrupt */
 956	mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
 957	mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
 958
 959	return 0;
 960}
 961
 962static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
 963{
 964	struct mixer_context *mixer_ctx = crtc->ctx;
 965	struct mixer_resources *res = &mixer_ctx->mixer_res;
 966
 967	__clear_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
 968
 969	if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
 970		return;
 971
 972	/* disable vsync interrupt */
 973	mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
 974	mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 975}
 976
 977static void mixer_atomic_begin(struct exynos_drm_crtc *crtc)
 
 978{
 979	struct mixer_context *mixer_ctx = crtc->ctx;
 
 
 980
 981	if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
 
 982		return;
 
 983
 984	mixer_vsync_set_update(mixer_ctx, false);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 985}
 986
 987static void mixer_update_plane(struct exynos_drm_crtc *crtc,
 988			       struct exynos_drm_plane *plane)
 989{
 990	struct mixer_context *mixer_ctx = crtc->ctx;
 
 991
 992	DRM_DEBUG_KMS("win: %d\n", plane->index);
 993
 994	if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
 
 
 995		return;
 
 
 996
 997	if (plane->index == VP_DEFAULT_WIN)
 998		vp_video_buffer(mixer_ctx, plane);
 999	else
1000		mixer_graph_buffer(mixer_ctx, plane);
 
 
1001}
1002
1003static void mixer_disable_plane(struct exynos_drm_crtc *crtc,
1004				struct exynos_drm_plane *plane)
1005{
1006	struct mixer_context *mixer_ctx = crtc->ctx;
1007	struct mixer_resources *res = &mixer_ctx->mixer_res;
 
1008	unsigned long flags;
1009
1010	DRM_DEBUG_KMS("win: %d\n", plane->index);
1011
1012	if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
 
 
 
1013		return;
 
 
1014
1015	spin_lock_irqsave(&res->reg_slock, flags);
1016	mixer_cfg_layer(mixer_ctx, plane->index, 0, false);
1017	spin_unlock_irqrestore(&res->reg_slock, flags);
1018}
1019
1020static void mixer_atomic_flush(struct exynos_drm_crtc *crtc)
1021{
1022	struct mixer_context *mixer_ctx = crtc->ctx;
1023
1024	if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
1025		return;
1026
1027	mixer_vsync_set_update(mixer_ctx, true);
 
 
 
1028}
1029
1030static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
1031{
1032	struct mixer_context *mixer_ctx = crtc->ctx;
1033	int err;
1034
1035	if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
1036		return;
1037
1038	err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe);
1039	if (err < 0) {
1040		DRM_DEBUG_KMS("failed to acquire vblank counter\n");
1041		return;
1042	}
 
1043
1044	atomic_set(&mixer_ctx->wait_vsync_event, 1);
1045
1046	/*
1047	 * wait for MIXER to signal VSYNC interrupt or return after
1048	 * timeout which is set to 50ms (refresh rate of 20).
1049	 */
1050	if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
1051				!atomic_read(&mixer_ctx->wait_vsync_event),
1052				HZ/20))
1053		DRM_DEBUG_KMS("vblank wait timed out.\n");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1054
1055	drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe);
 
 
 
 
 
 
1056}
1057
1058static void mixer_enable(struct exynos_drm_crtc *crtc)
1059{
1060	struct mixer_context *ctx = crtc->ctx;
1061	struct mixer_resources *res = &ctx->mixer_res;
1062
1063	if (test_bit(MXR_BIT_POWERED, &ctx->flags))
 
 
1064		return;
 
 
 
1065
1066	pm_runtime_get_sync(ctx->dev);
1067
1068	mixer_vsync_set_update(ctx, false);
1069
1070	mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1071
1072	if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) {
1073		mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
1074		mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
1075	}
1076	mixer_win_reset(ctx);
1077
1078	mixer_vsync_set_update(ctx, true);
 
1079
1080	set_bit(MXR_BIT_POWERED, &ctx->flags);
1081}
1082
1083static void mixer_disable(struct exynos_drm_crtc *crtc)
1084{
1085	struct mixer_context *ctx = crtc->ctx;
1086	int i;
1087
1088	if (!test_bit(MXR_BIT_POWERED, &ctx->flags))
1089		return;
 
 
1090
1091	mixer_stop(ctx);
1092	mixer_regs_dump(ctx);
 
1093
1094	for (i = 0; i < MIXER_WIN_NR; i++)
1095		mixer_disable_plane(crtc, &ctx->planes[i]);
 
 
 
1096
1097	pm_runtime_put(ctx->dev);
1098
1099	clear_bit(MXR_BIT_POWERED, &ctx->flags);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1100}
1101
1102/* Only valid for Mixer version 16.0.33.0 */
1103static int mixer_atomic_check(struct exynos_drm_crtc *crtc,
1104		       struct drm_crtc_state *state)
1105{
1106	struct drm_display_mode *mode = &state->adjusted_mode;
1107	u32 w, h;
1108
1109	w = mode->hdisplay;
1110	h = mode->vdisplay;
1111
1112	DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1113		mode->hdisplay, mode->vdisplay, mode->vrefresh,
1114		(mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1115
1116	if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1117		(w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1118		(w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1119		return 0;
1120
1121	return -EINVAL;
1122}
1123
1124static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
1125	.enable			= mixer_enable,
1126	.disable		= mixer_disable,
 
1127	.enable_vblank		= mixer_enable_vblank,
1128	.disable_vblank		= mixer_disable_vblank,
1129	.wait_for_vblank	= mixer_wait_for_vblank,
1130	.atomic_begin		= mixer_atomic_begin,
1131	.update_plane		= mixer_update_plane,
1132	.disable_plane		= mixer_disable_plane,
1133	.atomic_flush		= mixer_atomic_flush,
1134	.atomic_check		= mixer_atomic_check,
 
 
 
1135};
1136
1137static struct mixer_drv_data exynos5420_mxr_drv_data = {
1138	.version = MXR_VER_128_0_0_184,
1139	.is_vp_enabled = 0,
1140};
1141
1142static struct mixer_drv_data exynos5250_mxr_drv_data = {
1143	.version = MXR_VER_16_0_33_0,
1144	.is_vp_enabled = 0,
1145};
1146
1147static struct mixer_drv_data exynos4212_mxr_drv_data = {
1148	.version = MXR_VER_0_0_0_16,
1149	.is_vp_enabled = 1,
1150};
1151
1152static struct mixer_drv_data exynos4210_mxr_drv_data = {
1153	.version = MXR_VER_0_0_0_16,
1154	.is_vp_enabled = 1,
1155	.has_sclk = 1,
1156};
1157
1158static const struct platform_device_id mixer_driver_types[] = {
1159	{
1160		.name		= "s5p-mixer",
1161		.driver_data	= (unsigned long)&exynos4210_mxr_drv_data,
1162	}, {
1163		.name		= "exynos5-mixer",
1164		.driver_data	= (unsigned long)&exynos5250_mxr_drv_data,
1165	}, {
1166		/* end node */
1167	}
1168};
1169
1170static struct of_device_id mixer_match_types[] = {
1171	{
1172		.compatible = "samsung,exynos4210-mixer",
1173		.data	= &exynos4210_mxr_drv_data,
1174	}, {
1175		.compatible = "samsung,exynos4212-mixer",
1176		.data	= &exynos4212_mxr_drv_data,
1177	}, {
1178		.compatible = "samsung,exynos5-mixer",
1179		.data	= &exynos5250_mxr_drv_data,
1180	}, {
1181		.compatible = "samsung,exynos5250-mixer",
1182		.data	= &exynos5250_mxr_drv_data,
1183	}, {
1184		.compatible = "samsung,exynos5420-mixer",
1185		.data	= &exynos5420_mxr_drv_data,
1186	}, {
1187		/* end node */
1188	}
1189};
1190MODULE_DEVICE_TABLE(of, mixer_match_types);
1191
1192static int mixer_bind(struct device *dev, struct device *manager, void *data)
1193{
1194	struct mixer_context *ctx = dev_get_drvdata(dev);
1195	struct drm_device *drm_dev = data;
1196	struct exynos_drm_plane *exynos_plane;
1197	unsigned int i;
1198	int ret;
1199
1200	ret = mixer_initialize(ctx, drm_dev);
1201	if (ret)
1202		return ret;
1203
1204	for (i = 0; i < MIXER_WIN_NR; i++) {
1205		if (i == VP_DEFAULT_WIN && !ctx->vp_enabled)
1206			continue;
1207
1208		ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
1209					1 << ctx->pipe, &plane_configs[i]);
1210		if (ret)
1211			return ret;
1212	}
1213
1214	exynos_plane = &ctx->planes[DEFAULT_WIN];
1215	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
1216					   ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
1217					   &mixer_crtc_ops, ctx);
1218	if (IS_ERR(ctx->crtc)) {
1219		mixer_ctx_remove(ctx);
1220		ret = PTR_ERR(ctx->crtc);
1221		goto free_ctx;
1222	}
1223
1224	return 0;
1225
1226free_ctx:
1227	devm_kfree(dev, ctx);
1228	return ret;
1229}
1230
1231static void mixer_unbind(struct device *dev, struct device *master, void *data)
1232{
1233	struct mixer_context *ctx = dev_get_drvdata(dev);
1234
1235	mixer_ctx_remove(ctx);
1236}
1237
1238static const struct component_ops mixer_component_ops = {
1239	.bind	= mixer_bind,
1240	.unbind	= mixer_unbind,
1241};
1242
1243static int mixer_probe(struct platform_device *pdev)
1244{
1245	struct device *dev = &pdev->dev;
1246	struct mixer_drv_data *drv;
1247	struct mixer_context *ctx;
1248	int ret;
 
 
1249
1250	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1251	if (!ctx) {
1252		DRM_ERROR("failed to alloc mixer context.\n");
1253		return -ENOMEM;
1254	}
1255
 
 
1256	if (dev->of_node) {
1257		const struct of_device_id *match;
1258
1259		match = of_match_node(mixer_match_types, dev->of_node);
1260		drv = (struct mixer_drv_data *)match->data;
1261	} else {
1262		drv = (struct mixer_drv_data *)
1263			platform_get_device_id(pdev)->driver_data;
1264	}
1265
1266	ctx->pdev = pdev;
1267	ctx->dev = dev;
1268	ctx->vp_enabled = drv->is_vp_enabled;
1269	ctx->has_sclk = drv->has_sclk;
1270	ctx->mxr_ver = drv->version;
1271	init_waitqueue_head(&ctx->wait_vsync_queue);
1272	atomic_set(&ctx->wait_vsync_event, 0);
1273
1274	platform_set_drvdata(pdev, ctx);
1275
1276	ret = component_add(&pdev->dev, &mixer_component_ops);
1277	if (!ret)
1278		pm_runtime_enable(dev);
1279
1280	return ret;
1281}
1282
1283static int mixer_remove(struct platform_device *pdev)
1284{
1285	pm_runtime_disable(&pdev->dev);
1286
1287	component_del(&pdev->dev, &mixer_component_ops);
1288
1289	return 0;
1290}
1291
1292static int __maybe_unused exynos_mixer_suspend(struct device *dev)
1293{
1294	struct mixer_context *ctx = dev_get_drvdata(dev);
1295	struct mixer_resources *res = &ctx->mixer_res;
1296
1297	clk_disable_unprepare(res->hdmi);
1298	clk_disable_unprepare(res->mixer);
1299	if (ctx->vp_enabled) {
1300		clk_disable_unprepare(res->vp);
1301		if (ctx->has_sclk)
1302			clk_disable_unprepare(res->sclk_mixer);
1303	}
1304
1305	return 0;
1306}
1307
1308static int __maybe_unused exynos_mixer_resume(struct device *dev)
1309{
1310	struct mixer_context *ctx = dev_get_drvdata(dev);
1311	struct mixer_resources *res = &ctx->mixer_res;
1312	int ret;
1313
1314	ret = clk_prepare_enable(res->mixer);
1315	if (ret < 0) {
1316		DRM_ERROR("Failed to prepare_enable the mixer clk [%d]\n", ret);
1317		return ret;
1318	}
1319	ret = clk_prepare_enable(res->hdmi);
1320	if (ret < 0) {
1321		DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret);
1322		return ret;
1323	}
1324	if (ctx->vp_enabled) {
1325		ret = clk_prepare_enable(res->vp);
1326		if (ret < 0) {
1327			DRM_ERROR("Failed to prepare_enable the vp clk [%d]\n",
1328				  ret);
1329			return ret;
1330		}
1331		if (ctx->has_sclk) {
1332			ret = clk_prepare_enable(res->sclk_mixer);
1333			if (ret < 0) {
1334				DRM_ERROR("Failed to prepare_enable the " \
1335					   "sclk_mixer clk [%d]\n",
1336					  ret);
1337				return ret;
1338			}
1339		}
1340	}
1341
1342	return 0;
1343}
1344
1345static const struct dev_pm_ops exynos_mixer_pm_ops = {
1346	SET_RUNTIME_PM_OPS(exynos_mixer_suspend, exynos_mixer_resume, NULL)
1347};
1348
1349struct platform_driver mixer_driver = {
1350	.driver = {
1351		.name = "exynos-mixer",
1352		.owner = THIS_MODULE,
1353		.pm = &exynos_mixer_pm_ops,
1354		.of_match_table = mixer_match_types,
1355	},
1356	.probe = mixer_probe,
1357	.remove = mixer_remove,
1358	.id_table	= mixer_driver_types,
1359};
v3.15
   1/*
   2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
   3 * Authors:
   4 * Seung-Woo Kim <sw0312.kim@samsung.com>
   5 *	Inki Dae <inki.dae@samsung.com>
   6 *	Joonyoung Shim <jy0922.shim@samsung.com>
   7 *
   8 * Based on drivers/media/video/s5p-tv/mixer_reg.c
   9 *
  10 * This program is free software; you can redistribute  it and/or modify it
  11 * under  the terms of  the GNU General  Public License as published by the
  12 * Free Software Foundation;  either version 2 of the  License, or (at your
  13 * option) any later version.
  14 *
  15 */
  16
  17#include <drm/drmP.h>
  18
  19#include "regs-mixer.h"
  20#include "regs-vp.h"
  21
  22#include <linux/kernel.h>
  23#include <linux/spinlock.h>
  24#include <linux/wait.h>
  25#include <linux/i2c.h>
  26#include <linux/platform_device.h>
  27#include <linux/interrupt.h>
  28#include <linux/irq.h>
  29#include <linux/delay.h>
  30#include <linux/pm_runtime.h>
  31#include <linux/clk.h>
  32#include <linux/regulator/consumer.h>
  33#include <linux/of.h>
 
  34
  35#include <drm/exynos_drm.h>
  36
  37#include "exynos_drm_drv.h"
  38#include "exynos_drm_crtc.h"
 
 
  39#include "exynos_drm_iommu.h"
  40#include "exynos_mixer.h"
  41
  42#define get_mixer_manager(dev)	platform_get_drvdata(to_platform_device(dev))
  43
  44#define MIXER_WIN_NR		3
  45#define MIXER_DEFAULT_WIN	0
  46
  47struct hdmi_win_data {
  48	dma_addr_t		dma_addr;
  49	dma_addr_t		chroma_dma_addr;
  50	uint32_t		pixel_format;
  51	unsigned int		bpp;
  52	unsigned int		crtc_x;
  53	unsigned int		crtc_y;
  54	unsigned int		crtc_width;
  55	unsigned int		crtc_height;
  56	unsigned int		fb_x;
  57	unsigned int		fb_y;
  58	unsigned int		fb_width;
  59	unsigned int		fb_height;
  60	unsigned int		src_width;
  61	unsigned int		src_height;
  62	unsigned int		mode_width;
  63	unsigned int		mode_height;
  64	unsigned int		scan_flags;
  65	bool			enabled;
  66	bool			resume;
  67};
  68
  69struct mixer_resources {
  70	int			irq;
  71	void __iomem		*mixer_regs;
  72	void __iomem		*vp_regs;
  73	spinlock_t		reg_slock;
  74	struct clk		*mixer;
  75	struct clk		*vp;
 
  76	struct clk		*sclk_mixer;
  77	struct clk		*sclk_hdmi;
  78	struct clk		*sclk_dac;
  79};
  80
  81enum mixer_version_id {
  82	MXR_VER_0_0_0_16,
  83	MXR_VER_16_0_33_0,
  84	MXR_VER_128_0_0_184,
  85};
  86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  87struct mixer_context {
  88	struct platform_device *pdev;
  89	struct device		*dev;
  90	struct drm_device	*drm_dev;
 
 
  91	int			pipe;
 
  92	bool			interlace;
  93	bool			powered;
  94	bool			vp_enabled;
  95	u32			int_en;
  96
  97	struct mutex		mixer_mutex;
  98	struct mixer_resources	mixer_res;
  99	struct hdmi_win_data	win_data[MIXER_WIN_NR];
 100	enum mixer_version_id	mxr_ver;
 101	wait_queue_head_t	wait_vsync_queue;
 102	atomic_t		wait_vsync_event;
 103};
 104
 105struct mixer_drv_data {
 106	enum mixer_version_id	version;
 107	bool					is_vp_enabled;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 108};
 109
 110static const u8 filter_y_horiz_tap8[] = {
 111	0,	-1,	-1,	-1,	-1,	-1,	-1,	-1,
 112	-1,	-1,	-1,	-1,	-1,	0,	0,	0,
 113	0,	2,	4,	5,	6,	6,	6,	6,
 114	6,	5,	5,	4,	3,	2,	1,	1,
 115	0,	-6,	-12,	-16,	-18,	-20,	-21,	-20,
 116	-20,	-18,	-16,	-13,	-10,	-8,	-5,	-2,
 117	127,	126,	125,	121,	114,	107,	99,	89,
 118	79,	68,	57,	46,	35,	25,	16,	8,
 119};
 120
 121static const u8 filter_y_vert_tap4[] = {
 122	0,	-3,	-6,	-8,	-8,	-8,	-8,	-7,
 123	-6,	-5,	-4,	-3,	-2,	-1,	-1,	0,
 124	127,	126,	124,	118,	111,	102,	92,	81,
 125	70,	59,	48,	37,	27,	19,	11,	5,
 126	0,	5,	11,	19,	27,	37,	48,	59,
 127	70,	81,	92,	102,	111,	118,	124,	126,
 128	0,	0,	-1,	-1,	-2,	-3,	-4,	-5,
 129	-6,	-7,	-8,	-8,	-8,	-8,	-6,	-3,
 130};
 131
 132static const u8 filter_cr_horiz_tap4[] = {
 133	0,	-3,	-6,	-8,	-8,	-8,	-8,	-7,
 134	-6,	-5,	-4,	-3,	-2,	-1,	-1,	0,
 135	127,	126,	124,	118,	111,	102,	92,	81,
 136	70,	59,	48,	37,	27,	19,	11,	5,
 137};
 138
 
 
 
 
 
 
 
 
 
 
 
 
 139static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
 140{
 141	return readl(res->vp_regs + reg_id);
 142}
 143
 144static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
 145				 u32 val)
 146{
 147	writel(val, res->vp_regs + reg_id);
 148}
 149
 150static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
 151				 u32 val, u32 mask)
 152{
 153	u32 old = vp_reg_read(res, reg_id);
 154
 155	val = (val & mask) | (old & ~mask);
 156	writel(val, res->vp_regs + reg_id);
 157}
 158
 159static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
 160{
 161	return readl(res->mixer_regs + reg_id);
 162}
 163
 164static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
 165				 u32 val)
 166{
 167	writel(val, res->mixer_regs + reg_id);
 168}
 169
 170static inline void mixer_reg_writemask(struct mixer_resources *res,
 171				 u32 reg_id, u32 val, u32 mask)
 172{
 173	u32 old = mixer_reg_read(res, reg_id);
 174
 175	val = (val & mask) | (old & ~mask);
 176	writel(val, res->mixer_regs + reg_id);
 177}
 178
 179static void mixer_regs_dump(struct mixer_context *ctx)
 180{
 181#define DUMPREG(reg_id) \
 182do { \
 183	DRM_DEBUG_KMS(#reg_id " = %08x\n", \
 184		(u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
 185} while (0)
 186
 187	DUMPREG(MXR_STATUS);
 188	DUMPREG(MXR_CFG);
 189	DUMPREG(MXR_INT_EN);
 190	DUMPREG(MXR_INT_STATUS);
 191
 192	DUMPREG(MXR_LAYER_CFG);
 193	DUMPREG(MXR_VIDEO_CFG);
 194
 195	DUMPREG(MXR_GRAPHIC0_CFG);
 196	DUMPREG(MXR_GRAPHIC0_BASE);
 197	DUMPREG(MXR_GRAPHIC0_SPAN);
 198	DUMPREG(MXR_GRAPHIC0_WH);
 199	DUMPREG(MXR_GRAPHIC0_SXY);
 200	DUMPREG(MXR_GRAPHIC0_DXY);
 201
 202	DUMPREG(MXR_GRAPHIC1_CFG);
 203	DUMPREG(MXR_GRAPHIC1_BASE);
 204	DUMPREG(MXR_GRAPHIC1_SPAN);
 205	DUMPREG(MXR_GRAPHIC1_WH);
 206	DUMPREG(MXR_GRAPHIC1_SXY);
 207	DUMPREG(MXR_GRAPHIC1_DXY);
 208#undef DUMPREG
 209}
 210
 211static void vp_regs_dump(struct mixer_context *ctx)
 212{
 213#define DUMPREG(reg_id) \
 214do { \
 215	DRM_DEBUG_KMS(#reg_id " = %08x\n", \
 216		(u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
 217} while (0)
 218
 219	DUMPREG(VP_ENABLE);
 220	DUMPREG(VP_SRESET);
 221	DUMPREG(VP_SHADOW_UPDATE);
 222	DUMPREG(VP_FIELD_ID);
 223	DUMPREG(VP_MODE);
 224	DUMPREG(VP_IMG_SIZE_Y);
 225	DUMPREG(VP_IMG_SIZE_C);
 226	DUMPREG(VP_PER_RATE_CTRL);
 227	DUMPREG(VP_TOP_Y_PTR);
 228	DUMPREG(VP_BOT_Y_PTR);
 229	DUMPREG(VP_TOP_C_PTR);
 230	DUMPREG(VP_BOT_C_PTR);
 231	DUMPREG(VP_ENDIAN_MODE);
 232	DUMPREG(VP_SRC_H_POSITION);
 233	DUMPREG(VP_SRC_V_POSITION);
 234	DUMPREG(VP_SRC_WIDTH);
 235	DUMPREG(VP_SRC_HEIGHT);
 236	DUMPREG(VP_DST_H_POSITION);
 237	DUMPREG(VP_DST_V_POSITION);
 238	DUMPREG(VP_DST_WIDTH);
 239	DUMPREG(VP_DST_HEIGHT);
 240	DUMPREG(VP_H_RATIO);
 241	DUMPREG(VP_V_RATIO);
 242
 243#undef DUMPREG
 244}
 245
 246static inline void vp_filter_set(struct mixer_resources *res,
 247		int reg_id, const u8 *data, unsigned int size)
 248{
 249	/* assure 4-byte align */
 250	BUG_ON(size & 3);
 251	for (; size; size -= 4, reg_id += 4, data += 4) {
 252		u32 val = (data[0] << 24) |  (data[1] << 16) |
 253			(data[2] << 8) | data[3];
 254		vp_reg_write(res, reg_id, val);
 255	}
 256}
 257
 258static void vp_default_filter(struct mixer_resources *res)
 259{
 260	vp_filter_set(res, VP_POLY8_Y0_LL,
 261		filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
 262	vp_filter_set(res, VP_POLY4_Y0_LL,
 263		filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
 264	vp_filter_set(res, VP_POLY4_C0_LL,
 265		filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
 266}
 267
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 268static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
 269{
 270	struct mixer_resources *res = &ctx->mixer_res;
 271
 272	/* block update on vsync */
 273	mixer_reg_writemask(res, MXR_STATUS, enable ?
 274			MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
 275
 276	if (ctx->vp_enabled)
 277		vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
 278			VP_SHADOW_UPDATE_ENABLE : 0);
 279}
 280
 281static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
 282{
 283	struct mixer_resources *res = &ctx->mixer_res;
 284	u32 val;
 285
 286	/* choosing between interlace and progressive mode */
 287	val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
 288				MXR_CFG_SCAN_PROGRASSIVE);
 289
 290	if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
 291		/* choosing between proper HD and SD mode */
 292		if (height <= 480)
 293			val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
 294		else if (height <= 576)
 295			val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
 296		else if (height <= 720)
 297			val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
 298		else if (height <= 1080)
 299			val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
 300		else
 301			val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
 302	}
 303
 304	mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
 305}
 306
 307static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
 308{
 309	struct mixer_resources *res = &ctx->mixer_res;
 310	u32 val;
 311
 312	if (height == 480) {
 313		val = MXR_CFG_RGB601_0_255;
 314	} else if (height == 576) {
 315		val = MXR_CFG_RGB601_0_255;
 316	} else if (height == 720) {
 317		val = MXR_CFG_RGB709_16_235;
 318		mixer_reg_write(res, MXR_CM_COEFF_Y,
 319				(1 << 30) | (94 << 20) | (314 << 10) |
 320				(32 << 0));
 321		mixer_reg_write(res, MXR_CM_COEFF_CB,
 322				(972 << 20) | (851 << 10) | (225 << 0));
 323		mixer_reg_write(res, MXR_CM_COEFF_CR,
 324				(225 << 20) | (820 << 10) | (1004 << 0));
 325	} else if (height == 1080) {
 326		val = MXR_CFG_RGB709_16_235;
 327		mixer_reg_write(res, MXR_CM_COEFF_Y,
 328				(1 << 30) | (94 << 20) | (314 << 10) |
 329				(32 << 0));
 330		mixer_reg_write(res, MXR_CM_COEFF_CB,
 331				(972 << 20) | (851 << 10) | (225 << 0));
 332		mixer_reg_write(res, MXR_CM_COEFF_CR,
 333				(225 << 20) | (820 << 10) | (1004 << 0));
 334	} else {
 335		val = MXR_CFG_RGB709_16_235;
 336		mixer_reg_write(res, MXR_CM_COEFF_Y,
 337				(1 << 30) | (94 << 20) | (314 << 10) |
 338				(32 << 0));
 339		mixer_reg_write(res, MXR_CM_COEFF_CB,
 340				(972 << 20) | (851 << 10) | (225 << 0));
 341		mixer_reg_write(res, MXR_CM_COEFF_CR,
 342				(225 << 20) | (820 << 10) | (1004 << 0));
 343	}
 344
 345	mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
 346}
 347
 348static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
 
 349{
 350	struct mixer_resources *res = &ctx->mixer_res;
 351	u32 val = enable ? ~0 : 0;
 352
 353	switch (win) {
 354	case 0:
 355		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
 
 
 
 356		break;
 357	case 1:
 358		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
 
 
 
 359		break;
 360	case 2:
 361		if (ctx->vp_enabled) {
 362			vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
 363			mixer_reg_writemask(res, MXR_CFG, val,
 364				MXR_CFG_VP_ENABLE);
 
 
 
 365		}
 366		break;
 367	}
 368}
 369
 370static void mixer_run(struct mixer_context *ctx)
 371{
 372	struct mixer_resources *res = &ctx->mixer_res;
 373
 374	mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
 
 375
 376	mixer_regs_dump(ctx);
 
 
 
 
 
 
 
 
 
 377}
 378
 379static void vp_video_buffer(struct mixer_context *ctx, int win)
 
 380{
 
 
 
 381	struct mixer_resources *res = &ctx->mixer_res;
 
 382	unsigned long flags;
 383	struct hdmi_win_data *win_data;
 384	unsigned int x_ratio, y_ratio;
 385	unsigned int buf_num = 1;
 386	dma_addr_t luma_addr[2], chroma_addr[2];
 387	bool tiled_mode = false;
 388	bool crcb_mode = false;
 389	u32 val;
 390
 391	win_data = &ctx->win_data[win];
 392
 393	switch (win_data->pixel_format) {
 394	case DRM_FORMAT_NV12MT:
 395		tiled_mode = true;
 396	case DRM_FORMAT_NV12:
 397		crcb_mode = false;
 398		buf_num = 2;
 399		break;
 400	/* TODO: single buffer format NV12, NV21 */
 
 
 401	default:
 402		/* ignore pixel format at disable time */
 403		if (!win_data->dma_addr)
 404			break;
 405
 406		DRM_ERROR("pixel format for vp is wrong [%d].\n",
 407				win_data->pixel_format);
 408		return;
 409	}
 410
 411	/* scaling feature: (src << 16) / dst */
 412	x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
 413	y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
 414
 415	if (buf_num == 2) {
 416		luma_addr[0] = win_data->dma_addr;
 417		chroma_addr[0] = win_data->chroma_dma_addr;
 418	} else {
 419		luma_addr[0] = win_data->dma_addr;
 420		chroma_addr[0] = win_data->dma_addr
 421			+ (win_data->fb_width * win_data->fb_height);
 422	}
 423
 424	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
 425		ctx->interlace = true;
 426		if (tiled_mode) {
 427			luma_addr[1] = luma_addr[0] + 0x40;
 428			chroma_addr[1] = chroma_addr[0] + 0x40;
 429		} else {
 430			luma_addr[1] = luma_addr[0] + win_data->fb_width;
 431			chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
 432		}
 433	} else {
 434		ctx->interlace = false;
 435		luma_addr[1] = 0;
 436		chroma_addr[1] = 0;
 437	}
 438
 439	spin_lock_irqsave(&res->reg_slock, flags);
 440	mixer_vsync_set_update(ctx, false);
 441
 442	/* interlace or progressive scan mode */
 443	val = (ctx->interlace ? ~0 : 0);
 444	vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
 445
 446	/* setup format */
 447	val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
 448	val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
 449	vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
 450
 451	/* setting size of input image */
 452	vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
 453		VP_IMG_VSIZE(win_data->fb_height));
 454	/* chroma height has to reduced by 2 to avoid chroma distorions */
 455	vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
 456		VP_IMG_VSIZE(win_data->fb_height / 2));
 457
 458	vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
 459	vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
 460	vp_reg_write(res, VP_SRC_H_POSITION,
 461			VP_SRC_H_POSITION_VAL(win_data->fb_x));
 462	vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
 463
 464	vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
 465	vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
 466	if (ctx->interlace) {
 467		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
 468		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
 469	} else {
 470		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
 471		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
 472	}
 473
 474	vp_reg_write(res, VP_H_RATIO, x_ratio);
 475	vp_reg_write(res, VP_V_RATIO, y_ratio);
 476
 477	vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
 478
 479	/* set buffer address to vp */
 480	vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
 481	vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
 482	vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
 483	vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
 484
 485	mixer_cfg_scan(ctx, win_data->mode_height);
 486	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
 487	mixer_cfg_layer(ctx, win, true);
 
 488	mixer_run(ctx);
 489
 490	mixer_vsync_set_update(ctx, true);
 491	spin_unlock_irqrestore(&res->reg_slock, flags);
 492
 
 493	vp_regs_dump(ctx);
 494}
 495
 496static void mixer_layer_update(struct mixer_context *ctx)
 497{
 498	struct mixer_resources *res = &ctx->mixer_res;
 499	u32 val;
 500
 501	val = mixer_reg_read(res, MXR_CFG);
 502
 503	/* allow one update per vsync only */
 504	if (!(val & MXR_CFG_LAYER_UPDATE_COUNT_MASK))
 505		mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
 506}
 507
 508static void mixer_graph_buffer(struct mixer_context *ctx, int win)
 
 509{
 
 
 
 510	struct mixer_resources *res = &ctx->mixer_res;
 
 511	unsigned long flags;
 512	struct hdmi_win_data *win_data;
 513	unsigned int x_ratio, y_ratio;
 514	unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
 515	dma_addr_t dma_addr;
 516	unsigned int fmt;
 517	u32 val;
 518
 519	win_data = &ctx->win_data[win];
 
 
 
 
 520
 521	#define RGB565 4
 522	#define ARGB1555 5
 523	#define ARGB4444 6
 524	#define ARGB8888 7
 525
 526	switch (win_data->bpp) {
 527	case 16:
 528		fmt = ARGB4444;
 529		break;
 530	case 32:
 531		fmt = ARGB8888;
 
 532		break;
 
 
 
 
 
 
 533	default:
 534		fmt = ARGB8888;
 
 535	}
 536
 537	/* 2x scaling feature */
 538	x_ratio = 0;
 539	y_ratio = 0;
 540
 541	dst_x_offset = win_data->crtc_x;
 542	dst_y_offset = win_data->crtc_y;
 543
 544	/* converting dma address base and source offset */
 545	dma_addr = win_data->dma_addr
 546		+ (win_data->fb_x * win_data->bpp >> 3)
 547		+ (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
 548	src_x_offset = 0;
 549	src_y_offset = 0;
 550
 551	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
 552		ctx->interlace = true;
 553	else
 554		ctx->interlace = false;
 555
 556	spin_lock_irqsave(&res->reg_slock, flags);
 557	mixer_vsync_set_update(ctx, false);
 558
 559	/* setup format */
 560	mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
 561		MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
 562
 563	/* setup geometry */
 564	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
 
 565
 566	/* setup display size */
 567	if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
 568		win == MIXER_DEFAULT_WIN) {
 569		val  = MXR_MXR_RES_HEIGHT(win_data->fb_height);
 570		val |= MXR_MXR_RES_WIDTH(win_data->fb_width);
 571		mixer_reg_write(res, MXR_RESOLUTION, val);
 572	}
 573
 574	val  = MXR_GRP_WH_WIDTH(win_data->crtc_width);
 575	val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
 576	val |= MXR_GRP_WH_H_SCALE(x_ratio);
 577	val |= MXR_GRP_WH_V_SCALE(y_ratio);
 578	mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
 579
 580	/* setup offsets in source image */
 581	val  = MXR_GRP_SXY_SX(src_x_offset);
 582	val |= MXR_GRP_SXY_SY(src_y_offset);
 583	mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
 584
 585	/* setup offsets in display image */
 586	val  = MXR_GRP_DXY_DX(dst_x_offset);
 587	val |= MXR_GRP_DXY_DY(dst_y_offset);
 588	mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
 589
 590	/* set buffer address to mixer */
 591	mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
 592
 593	mixer_cfg_scan(ctx, win_data->mode_height);
 594	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
 595	mixer_cfg_layer(ctx, win, true);
 
 596
 597	/* layer update mandatory for mixer 16.0.33.0 */
 598	if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
 599		ctx->mxr_ver == MXR_VER_128_0_0_184)
 600		mixer_layer_update(ctx);
 601
 602	mixer_run(ctx);
 603
 604	mixer_vsync_set_update(ctx, true);
 605	spin_unlock_irqrestore(&res->reg_slock, flags);
 
 
 606}
 607
 608static void vp_win_reset(struct mixer_context *ctx)
 609{
 610	struct mixer_resources *res = &ctx->mixer_res;
 611	int tries = 100;
 612
 613	vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
 614	for (tries = 100; tries; --tries) {
 615		/* waiting until VP_SRESET_PROCESSING is 0 */
 616		if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
 617			break;
 618		usleep_range(10000, 12000);
 619	}
 620	WARN(tries == 0, "failed to reset Video Processor\n");
 621}
 622
 623static void mixer_win_reset(struct mixer_context *ctx)
 624{
 625	struct mixer_resources *res = &ctx->mixer_res;
 626	unsigned long flags;
 627	u32 val; /* value stored to register */
 628
 629	spin_lock_irqsave(&res->reg_slock, flags);
 630	mixer_vsync_set_update(ctx, false);
 631
 632	mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
 633
 634	/* set output in RGB888 mode */
 635	mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
 636
 637	/* 16 beat burst in DMA */
 638	mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
 639		MXR_STATUS_BURST_MASK);
 640
 641	/* setting default layer priority: layer1 > layer0 > video
 642	 * because typical usage scenario would be
 643	 * layer1 - OSD
 644	 * layer0 - framebuffer
 645	 * video - video overlay
 646	 */
 647	val = MXR_LAYER_CFG_GRP1_VAL(3);
 648	val |= MXR_LAYER_CFG_GRP0_VAL(2);
 649	if (ctx->vp_enabled)
 650		val |= MXR_LAYER_CFG_VP_VAL(1);
 651	mixer_reg_write(res, MXR_LAYER_CFG, val);
 652
 653	/* setting background color */
 654	mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
 655	mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
 656	mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
 657
 658	/* setting graphical layers */
 659	val  = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
 660	val |= MXR_GRP_CFG_WIN_BLEND_EN;
 661	val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
 662
 663	/* Don't blend layer 0 onto the mixer background */
 664	mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
 665
 666	/* Blend layer 1 into layer 0 */
 667	val |= MXR_GRP_CFG_BLEND_PRE_MUL;
 668	val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
 669	mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
 670
 671	/* setting video layers */
 672	val = MXR_GRP_CFG_ALPHA_VAL(0);
 673	mixer_reg_write(res, MXR_VIDEO_CFG, val);
 674
 675	if (ctx->vp_enabled) {
 676		/* configuration of Video Processor Registers */
 677		vp_win_reset(ctx);
 678		vp_default_filter(res);
 679	}
 680
 681	/* disable all layers */
 682	mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
 683	mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
 684	if (ctx->vp_enabled)
 685		mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
 686
 687	mixer_vsync_set_update(ctx, true);
 688	spin_unlock_irqrestore(&res->reg_slock, flags);
 689}
 690
 691static irqreturn_t mixer_irq_handler(int irq, void *arg)
 692{
 693	struct mixer_context *ctx = arg;
 694	struct mixer_resources *res = &ctx->mixer_res;
 695	u32 val, base, shadow;
 
 696
 697	spin_lock(&res->reg_slock);
 698
 699	/* read interrupt status for handling and clearing flags for VSYNC */
 700	val = mixer_reg_read(res, MXR_INT_STATUS);
 701
 702	/* handling VSYNC */
 703	if (val & MXR_INT_STATUS_VSYNC) {
 
 
 
 
 704		/* interlace scan need to check shadow register */
 705		if (ctx->interlace) {
 706			base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
 707			shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
 708			if (base != shadow)
 709				goto out;
 710
 711			base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
 712			shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
 713			if (base != shadow)
 714				goto out;
 715		}
 716
 717		drm_handle_vblank(ctx->drm_dev, ctx->pipe);
 718		exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
 
 
 
 
 
 
 
 719
 720		/* set wait vsync event to zero and wake up queue. */
 721		if (atomic_read(&ctx->wait_vsync_event)) {
 722			atomic_set(&ctx->wait_vsync_event, 0);
 723			wake_up(&ctx->wait_vsync_queue);
 724		}
 725	}
 726
 727out:
 728	/* clear interrupts */
 729	if (~val & MXR_INT_EN_VSYNC) {
 730		/* vsync interrupt use different bit for read and clear */
 731		val &= ~MXR_INT_EN_VSYNC;
 732		val |= MXR_INT_CLEAR_VSYNC;
 733	}
 734	mixer_reg_write(res, MXR_INT_STATUS, val);
 735
 736	spin_unlock(&res->reg_slock);
 737
 738	return IRQ_HANDLED;
 739}
 740
 741static int mixer_resources_init(struct mixer_context *mixer_ctx)
 742{
 743	struct device *dev = &mixer_ctx->pdev->dev;
 744	struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
 745	struct resource *res;
 746	int ret;
 747
 748	spin_lock_init(&mixer_res->reg_slock);
 749
 750	mixer_res->mixer = devm_clk_get(dev, "mixer");
 751	if (IS_ERR(mixer_res->mixer)) {
 752		dev_err(dev, "failed to get clock 'mixer'\n");
 753		return -ENODEV;
 754	}
 755
 
 
 
 
 
 
 756	mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
 757	if (IS_ERR(mixer_res->sclk_hdmi)) {
 758		dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
 759		return -ENODEV;
 760	}
 761	res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
 762	if (res == NULL) {
 763		dev_err(dev, "get memory resource failed.\n");
 764		return -ENXIO;
 765	}
 766
 767	mixer_res->mixer_regs = devm_ioremap(dev, res->start,
 768							resource_size(res));
 769	if (mixer_res->mixer_regs == NULL) {
 770		dev_err(dev, "register mapping failed.\n");
 771		return -ENXIO;
 772	}
 773
 774	res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
 775	if (res == NULL) {
 776		dev_err(dev, "get interrupt resource failed.\n");
 777		return -ENXIO;
 778	}
 779
 780	ret = devm_request_irq(dev, res->start, mixer_irq_handler,
 781						0, "drm_mixer", mixer_ctx);
 782	if (ret) {
 783		dev_err(dev, "request interrupt failed.\n");
 784		return ret;
 785	}
 786	mixer_res->irq = res->start;
 787
 788	return 0;
 789}
 790
 791static int vp_resources_init(struct mixer_context *mixer_ctx)
 792{
 793	struct device *dev = &mixer_ctx->pdev->dev;
 794	struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
 795	struct resource *res;
 796
 797	mixer_res->vp = devm_clk_get(dev, "vp");
 798	if (IS_ERR(mixer_res->vp)) {
 799		dev_err(dev, "failed to get clock 'vp'\n");
 800		return -ENODEV;
 801	}
 802	mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
 803	if (IS_ERR(mixer_res->sclk_mixer)) {
 804		dev_err(dev, "failed to get clock 'sclk_mixer'\n");
 805		return -ENODEV;
 806	}
 807	mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
 808	if (IS_ERR(mixer_res->sclk_dac)) {
 809		dev_err(dev, "failed to get clock 'sclk_dac'\n");
 810		return -ENODEV;
 
 
 
 
 
 
 
 811	}
 812
 813	if (mixer_res->sclk_hdmi)
 814		clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
 815
 816	res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
 817	if (res == NULL) {
 818		dev_err(dev, "get memory resource failed.\n");
 819		return -ENXIO;
 820	}
 821
 822	mixer_res->vp_regs = devm_ioremap(dev, res->start,
 823							resource_size(res));
 824	if (mixer_res->vp_regs == NULL) {
 825		dev_err(dev, "register mapping failed.\n");
 826		return -ENXIO;
 827	}
 828
 829	return 0;
 830}
 831
 832static int mixer_initialize(struct exynos_drm_manager *mgr,
 833			struct drm_device *drm_dev, int pipe)
 834{
 835	int ret;
 836	struct mixer_context *mixer_ctx = mgr->ctx;
 
 837
 838	mixer_ctx->drm_dev = drm_dev;
 839	mixer_ctx->pipe = pipe;
 840
 841	/* acquire resources: regs, irqs, clocks */
 842	ret = mixer_resources_init(mixer_ctx);
 843	if (ret) {
 844		DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
 845		return ret;
 846	}
 847
 848	if (mixer_ctx->vp_enabled) {
 849		/* acquire vp resources: regs, irqs, clocks */
 850		ret = vp_resources_init(mixer_ctx);
 851		if (ret) {
 852			DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
 853			return ret;
 854		}
 855	}
 856
 857	if (!is_drm_iommu_supported(mixer_ctx->drm_dev))
 858		return 0;
 
 859
 860	return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
 861}
 862
 863static void mixer_mgr_remove(struct exynos_drm_manager *mgr)
 864{
 865	struct mixer_context *mixer_ctx = mgr->ctx;
 866
 867	if (is_drm_iommu_supported(mixer_ctx->drm_dev))
 868		drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
 869}
 870
 871static int mixer_enable_vblank(struct exynos_drm_manager *mgr)
 872{
 873	struct mixer_context *mixer_ctx = mgr->ctx;
 874	struct mixer_resources *res = &mixer_ctx->mixer_res;
 875
 876	if (!mixer_ctx->powered) {
 877		mixer_ctx->int_en |= MXR_INT_EN_VSYNC;
 878		return 0;
 879	}
 880
 881	/* enable vsync interrupt */
 882	mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
 883			MXR_INT_EN_VSYNC);
 884
 885	return 0;
 886}
 887
 888static void mixer_disable_vblank(struct exynos_drm_manager *mgr)
 889{
 890	struct mixer_context *mixer_ctx = mgr->ctx;
 891	struct mixer_resources *res = &mixer_ctx->mixer_res;
 892
 
 
 
 
 
 893	/* disable vsync interrupt */
 
 894	mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 895}
 896
 897static void mixer_win_mode_set(struct exynos_drm_manager *mgr,
 898			struct exynos_drm_overlay *overlay)
 899{
 900	struct mixer_context *mixer_ctx = mgr->ctx;
 901	struct hdmi_win_data *win_data;
 902	int win;
 903
 904	if (!overlay) {
 905		DRM_ERROR("overlay is NULL\n");
 906		return;
 907	}
 908
 909	DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
 910				 overlay->fb_width, overlay->fb_height,
 911				 overlay->fb_x, overlay->fb_y,
 912				 overlay->crtc_width, overlay->crtc_height,
 913				 overlay->crtc_x, overlay->crtc_y);
 914
 915	win = overlay->zpos;
 916	if (win == DEFAULT_ZPOS)
 917		win = MIXER_DEFAULT_WIN;
 918
 919	if (win < 0 || win >= MIXER_WIN_NR) {
 920		DRM_ERROR("mixer window[%d] is wrong\n", win);
 921		return;
 922	}
 923
 924	win_data = &mixer_ctx->win_data[win];
 925
 926	win_data->dma_addr = overlay->dma_addr[0];
 927	win_data->chroma_dma_addr = overlay->dma_addr[1];
 928	win_data->pixel_format = overlay->pixel_format;
 929	win_data->bpp = overlay->bpp;
 930
 931	win_data->crtc_x = overlay->crtc_x;
 932	win_data->crtc_y = overlay->crtc_y;
 933	win_data->crtc_width = overlay->crtc_width;
 934	win_data->crtc_height = overlay->crtc_height;
 935
 936	win_data->fb_x = overlay->fb_x;
 937	win_data->fb_y = overlay->fb_y;
 938	win_data->fb_width = overlay->fb_width;
 939	win_data->fb_height = overlay->fb_height;
 940	win_data->src_width = overlay->src_width;
 941	win_data->src_height = overlay->src_height;
 942
 943	win_data->mode_width = overlay->mode_width;
 944	win_data->mode_height = overlay->mode_height;
 945
 946	win_data->scan_flags = overlay->scan_flag;
 947}
 948
 949static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos)
 
 950{
 951	struct mixer_context *mixer_ctx = mgr->ctx;
 952	int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
 953
 954	DRM_DEBUG_KMS("win: %d\n", win);
 955
 956	mutex_lock(&mixer_ctx->mixer_mutex);
 957	if (!mixer_ctx->powered) {
 958		mutex_unlock(&mixer_ctx->mixer_mutex);
 959		return;
 960	}
 961	mutex_unlock(&mixer_ctx->mixer_mutex);
 962
 963	if (win > 1 && mixer_ctx->vp_enabled)
 964		vp_video_buffer(mixer_ctx, win);
 965	else
 966		mixer_graph_buffer(mixer_ctx, win);
 967
 968	mixer_ctx->win_data[win].enabled = true;
 969}
 970
 971static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
 
 972{
 973	struct mixer_context *mixer_ctx = mgr->ctx;
 974	struct mixer_resources *res = &mixer_ctx->mixer_res;
 975	int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
 976	unsigned long flags;
 977
 978	DRM_DEBUG_KMS("win: %d\n", win);
 979
 980	mutex_lock(&mixer_ctx->mixer_mutex);
 981	if (!mixer_ctx->powered) {
 982		mutex_unlock(&mixer_ctx->mixer_mutex);
 983		mixer_ctx->win_data[win].resume = false;
 984		return;
 985	}
 986	mutex_unlock(&mixer_ctx->mixer_mutex);
 987
 988	spin_lock_irqsave(&res->reg_slock, flags);
 989	mixer_vsync_set_update(mixer_ctx, false);
 
 
 
 
 
 
 990
 991	mixer_cfg_layer(mixer_ctx, win, false);
 
 992
 993	mixer_vsync_set_update(mixer_ctx, true);
 994	spin_unlock_irqrestore(&res->reg_slock, flags);
 995
 996	mixer_ctx->win_data[win].enabled = false;
 997}
 998
 999static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
1000{
1001	struct mixer_context *mixer_ctx = mgr->ctx;
 
 
 
 
1002
1003	mutex_lock(&mixer_ctx->mixer_mutex);
1004	if (!mixer_ctx->powered) {
1005		mutex_unlock(&mixer_ctx->mixer_mutex);
1006		return;
1007	}
1008	mutex_unlock(&mixer_ctx->mixer_mutex);
1009
1010	atomic_set(&mixer_ctx->wait_vsync_event, 1);
1011
1012	/*
1013	 * wait for MIXER to signal VSYNC interrupt or return after
1014	 * timeout which is set to 50ms (refresh rate of 20).
1015	 */
1016	if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
1017				!atomic_read(&mixer_ctx->wait_vsync_event),
1018				HZ/20))
1019		DRM_DEBUG_KMS("vblank wait timed out.\n");
1020}
1021
1022static void mixer_window_suspend(struct exynos_drm_manager *mgr)
1023{
1024	struct mixer_context *ctx = mgr->ctx;
1025	struct hdmi_win_data *win_data;
1026	int i;
1027
1028	for (i = 0; i < MIXER_WIN_NR; i++) {
1029		win_data = &ctx->win_data[i];
1030		win_data->resume = win_data->enabled;
1031		mixer_win_disable(mgr, i);
1032	}
1033	mixer_wait_for_vblank(mgr);
1034}
1035
1036static void mixer_window_resume(struct exynos_drm_manager *mgr)
1037{
1038	struct mixer_context *ctx = mgr->ctx;
1039	struct hdmi_win_data *win_data;
1040	int i;
1041
1042	for (i = 0; i < MIXER_WIN_NR; i++) {
1043		win_data = &ctx->win_data[i];
1044		win_data->enabled = win_data->resume;
1045		win_data->resume = false;
1046		if (win_data->enabled)
1047			mixer_win_commit(mgr, i);
1048	}
1049}
1050
1051static void mixer_poweron(struct exynos_drm_manager *mgr)
1052{
1053	struct mixer_context *ctx = mgr->ctx;
1054	struct mixer_resources *res = &ctx->mixer_res;
1055
1056	mutex_lock(&ctx->mixer_mutex);
1057	if (ctx->powered) {
1058		mutex_unlock(&ctx->mixer_mutex);
1059		return;
1060	}
1061	ctx->powered = true;
1062	mutex_unlock(&ctx->mixer_mutex);
1063
1064	pm_runtime_get_sync(ctx->dev);
1065
1066	clk_prepare_enable(res->mixer);
1067	if (ctx->vp_enabled) {
1068		clk_prepare_enable(res->vp);
1069		clk_prepare_enable(res->sclk_mixer);
 
 
 
1070	}
 
1071
1072	mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
1073	mixer_win_reset(ctx);
1074
1075	mixer_window_resume(mgr);
1076}
1077
1078static void mixer_poweroff(struct exynos_drm_manager *mgr)
1079{
1080	struct mixer_context *ctx = mgr->ctx;
1081	struct mixer_resources *res = &ctx->mixer_res;
1082
1083	mutex_lock(&ctx->mixer_mutex);
1084	if (!ctx->powered)
1085		goto out;
1086	mutex_unlock(&ctx->mixer_mutex);
1087
1088	mixer_window_suspend(mgr);
1089
1090	ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
1091
1092	clk_disable_unprepare(res->mixer);
1093	if (ctx->vp_enabled) {
1094		clk_disable_unprepare(res->vp);
1095		clk_disable_unprepare(res->sclk_mixer);
1096	}
1097
1098	pm_runtime_put_sync(ctx->dev);
1099
1100	mutex_lock(&ctx->mixer_mutex);
1101	ctx->powered = false;
1102
1103out:
1104	mutex_unlock(&ctx->mixer_mutex);
1105}
1106
1107static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
1108{
1109	switch (mode) {
1110	case DRM_MODE_DPMS_ON:
1111		mixer_poweron(mgr);
1112		break;
1113	case DRM_MODE_DPMS_STANDBY:
1114	case DRM_MODE_DPMS_SUSPEND:
1115	case DRM_MODE_DPMS_OFF:
1116		mixer_poweroff(mgr);
1117		break;
1118	default:
1119		DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1120		break;
1121	}
1122}
1123
1124/* Only valid for Mixer version 16.0.33.0 */
1125int mixer_check_mode(struct drm_display_mode *mode)
 
1126{
 
1127	u32 w, h;
1128
1129	w = mode->hdisplay;
1130	h = mode->vdisplay;
1131
1132	DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1133		mode->hdisplay, mode->vdisplay, mode->vrefresh,
1134		(mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1135
1136	if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1137		(w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1138		(w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1139		return 0;
1140
1141	return -EINVAL;
1142}
1143
1144static struct exynos_drm_manager_ops mixer_manager_ops = {
1145	.initialize		= mixer_initialize,
1146	.remove			= mixer_mgr_remove,
1147	.dpms			= mixer_dpms,
1148	.enable_vblank		= mixer_enable_vblank,
1149	.disable_vblank		= mixer_disable_vblank,
1150	.wait_for_vblank	= mixer_wait_for_vblank,
1151	.win_mode_set		= mixer_win_mode_set,
1152	.win_commit		= mixer_win_commit,
1153	.win_disable		= mixer_win_disable,
1154};
1155
1156static struct exynos_drm_manager mixer_manager = {
1157	.type			= EXYNOS_DISPLAY_TYPE_HDMI,
1158	.ops			= &mixer_manager_ops,
1159};
1160
1161static struct mixer_drv_data exynos5420_mxr_drv_data = {
1162	.version = MXR_VER_128_0_0_184,
1163	.is_vp_enabled = 0,
1164};
1165
1166static struct mixer_drv_data exynos5250_mxr_drv_data = {
1167	.version = MXR_VER_16_0_33_0,
1168	.is_vp_enabled = 0,
1169};
1170
 
 
 
 
 
1171static struct mixer_drv_data exynos4210_mxr_drv_data = {
1172	.version = MXR_VER_0_0_0_16,
1173	.is_vp_enabled = 1,
 
1174};
1175
1176static struct platform_device_id mixer_driver_types[] = {
1177	{
1178		.name		= "s5p-mixer",
1179		.driver_data	= (unsigned long)&exynos4210_mxr_drv_data,
1180	}, {
1181		.name		= "exynos5-mixer",
1182		.driver_data	= (unsigned long)&exynos5250_mxr_drv_data,
1183	}, {
1184		/* end node */
1185	}
1186};
1187
1188static struct of_device_id mixer_match_types[] = {
1189	{
 
 
 
 
 
 
1190		.compatible = "samsung,exynos5-mixer",
1191		.data	= &exynos5250_mxr_drv_data,
1192	}, {
1193		.compatible = "samsung,exynos5250-mixer",
1194		.data	= &exynos5250_mxr_drv_data,
1195	}, {
1196		.compatible = "samsung,exynos5420-mixer",
1197		.data	= &exynos5420_mxr_drv_data,
1198	}, {
1199		/* end node */
1200	}
1201};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1202
1203static int mixer_probe(struct platform_device *pdev)
1204{
1205	struct device *dev = &pdev->dev;
 
1206	struct mixer_context *ctx;
1207	struct mixer_drv_data *drv;
1208
1209	dev_info(dev, "probe start\n");
1210
1211	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1212	if (!ctx) {
1213		DRM_ERROR("failed to alloc mixer context.\n");
1214		return -ENOMEM;
1215	}
1216
1217	mutex_init(&ctx->mixer_mutex);
1218
1219	if (dev->of_node) {
1220		const struct of_device_id *match;
 
1221		match = of_match_node(mixer_match_types, dev->of_node);
1222		drv = (struct mixer_drv_data *)match->data;
1223	} else {
1224		drv = (struct mixer_drv_data *)
1225			platform_get_device_id(pdev)->driver_data;
1226	}
1227
1228	ctx->pdev = pdev;
1229	ctx->dev = dev;
1230	ctx->vp_enabled = drv->is_vp_enabled;
 
1231	ctx->mxr_ver = drv->version;
1232	init_waitqueue_head(&ctx->wait_vsync_queue);
1233	atomic_set(&ctx->wait_vsync_event, 0);
1234
1235	mixer_manager.ctx = ctx;
1236	platform_set_drvdata(pdev, &mixer_manager);
1237	exynos_drm_manager_register(&mixer_manager);
 
 
 
 
 
 
 
 
 
1238
1239	pm_runtime_enable(dev);
1240
1241	return 0;
1242}
1243
1244static int mixer_remove(struct platform_device *pdev)
1245{
1246	dev_info(&pdev->dev, "remove successful\n");
 
1247
1248	pm_runtime_disable(&pdev->dev);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1249
1250	return 0;
1251}
1252
 
 
 
 
1253struct platform_driver mixer_driver = {
1254	.driver = {
1255		.name = "exynos-mixer",
1256		.owner = THIS_MODULE,
 
1257		.of_match_table = mixer_match_types,
1258	},
1259	.probe = mixer_probe,
1260	.remove = mixer_remove,
1261	.id_table	= mixer_driver_types,
1262};