PageRenderTime 178ms CodeModel.GetById 43ms app.highlight 105ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/video/omap2/dss/dispc.c

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t
C | 3780 lines | 2977 code | 660 blank | 143 comment | 543 complexity | 903a9a937cfbcc11572746619aab0c7d MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * linux/drivers/video/omap2/dss/dispc.c
   3 *
   4 * Copyright (C) 2009 Nokia Corporation
   5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
   6 *
   7 * Some code and ideas taken from drivers/video/omap/ driver
   8 * by Imre Deak.
   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 version 2 as published by
  12 * the Free Software Foundation.
  13 *
  14 * This program is distributed in the hope that it will be useful, but WITHOUT
  15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  17 * more details.
  18 *
  19 * You should have received a copy of the GNU General Public License along with
  20 * this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22
  23#define DSS_SUBSYS_NAME "DISPC"
  24
  25#include <linux/kernel.h>
  26#include <linux/dma-mapping.h>
  27#include <linux/vmalloc.h>
  28#include <linux/clk.h>
  29#include <linux/io.h>
  30#include <linux/jiffies.h>
  31#include <linux/seq_file.h>
  32#include <linux/delay.h>
  33#include <linux/workqueue.h>
  34#include <linux/hardirq.h>
  35#include <linux/interrupt.h>
  36#include <linux/platform_device.h>
  37#include <linux/pm_runtime.h>
  38
  39#include <plat/sram.h>
  40#include <plat/clock.h>
  41
  42#include <video/omapdss.h>
  43
  44#include "dss.h"
  45#include "dss_features.h"
  46#include "dispc.h"
  47
  48/* DISPC */
  49#define DISPC_SZ_REGS			SZ_4K
  50
  51#define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
  52					 DISPC_IRQ_OCP_ERR | \
  53					 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
  54					 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
  55					 DISPC_IRQ_SYNC_LOST | \
  56					 DISPC_IRQ_SYNC_LOST_DIGIT)
  57
  58#define DISPC_MAX_NR_ISRS		8
  59
  60struct omap_dispc_isr_data {
  61	omap_dispc_isr_t	isr;
  62	void			*arg;
  63	u32			mask;
  64};
  65
  66struct dispc_h_coef {
  67	s8 hc4;
  68	s8 hc3;
  69	u8 hc2;
  70	s8 hc1;
  71	s8 hc0;
  72};
  73
  74struct dispc_v_coef {
  75	s8 vc22;
  76	s8 vc2;
  77	u8 vc1;
  78	s8 vc0;
  79	s8 vc00;
  80};
  81
  82enum omap_burst_size {
  83	BURST_SIZE_X2 = 0,
  84	BURST_SIZE_X4 = 1,
  85	BURST_SIZE_X8 = 2,
  86};
  87
  88#define REG_GET(idx, start, end) \
  89	FLD_GET(dispc_read_reg(idx), start, end)
  90
  91#define REG_FLD_MOD(idx, val, start, end)				\
  92	dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
  93
  94struct dispc_irq_stats {
  95	unsigned long last_reset;
  96	unsigned irq_count;
  97	unsigned irqs[32];
  98};
  99
 100static struct {
 101	struct platform_device *pdev;
 102	void __iomem    *base;
 103
 104	int		ctx_loss_cnt;
 105
 106	int irq;
 107	struct clk *dss_clk;
 108
 109	u32	fifo_size[3];
 110
 111	spinlock_t irq_lock;
 112	u32 irq_error_mask;
 113	struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
 114	u32 error_irqs;
 115	struct work_struct error_work;
 116
 117	bool		ctx_valid;
 118	u32		ctx[DISPC_SZ_REGS / sizeof(u32)];
 119
 120#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
 121	spinlock_t irq_stats_lock;
 122	struct dispc_irq_stats irq_stats;
 123#endif
 124} dispc;
 125
 126enum omap_color_component {
 127	/* used for all color formats for OMAP3 and earlier
 128	 * and for RGB and Y color component on OMAP4
 129	 */
 130	DISPC_COLOR_COMPONENT_RGB_Y		= 1 << 0,
 131	/* used for UV component for
 132	 * OMAP_DSS_COLOR_YUV2, OMAP_DSS_COLOR_UYVY, OMAP_DSS_COLOR_NV12
 133	 * color formats on OMAP4
 134	 */
 135	DISPC_COLOR_COMPONENT_UV		= 1 << 1,
 136};
 137
 138static void _omap_dispc_set_irqs(void);
 139
 140static inline void dispc_write_reg(const u16 idx, u32 val)
 141{
 142	__raw_writel(val, dispc.base + idx);
 143}
 144
 145static inline u32 dispc_read_reg(const u16 idx)
 146{
 147	return __raw_readl(dispc.base + idx);
 148}
 149
 150static int dispc_get_ctx_loss_count(void)
 151{
 152	struct device *dev = &dispc.pdev->dev;
 153	struct omap_display_platform_data *pdata = dev->platform_data;
 154	struct omap_dss_board_info *board_data = pdata->board_data;
 155	int cnt;
 156
 157	if (!board_data->get_context_loss_count)
 158		return -ENOENT;
 159
 160	cnt = board_data->get_context_loss_count(dev);
 161
 162	WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
 163
 164	return cnt;
 165}
 166
 167#define SR(reg) \
 168	dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
 169#define RR(reg) \
 170	dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
 171
 172static void dispc_save_context(void)
 173{
 174	int i;
 175
 176	DSSDBG("dispc_save_context\n");
 177
 178	SR(IRQENABLE);
 179	SR(CONTROL);
 180	SR(CONFIG);
 181	SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
 182	SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
 183	SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
 184	SR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
 185	SR(LINE_NUMBER);
 186	SR(TIMING_H(OMAP_DSS_CHANNEL_LCD));
 187	SR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
 188	SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
 189	SR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
 190	if (dss_has_feature(FEAT_GLOBAL_ALPHA))
 191		SR(GLOBAL_ALPHA);
 192	SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
 193	SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
 194	if (dss_has_feature(FEAT_MGR_LCD2)) {
 195		SR(CONTROL2);
 196		SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
 197		SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
 198		SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
 199		SR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
 200		SR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
 201		SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
 202		SR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
 203		SR(CONFIG2);
 204	}
 205
 206	SR(OVL_BA0(OMAP_DSS_GFX));
 207	SR(OVL_BA1(OMAP_DSS_GFX));
 208	SR(OVL_POSITION(OMAP_DSS_GFX));
 209	SR(OVL_SIZE(OMAP_DSS_GFX));
 210	SR(OVL_ATTRIBUTES(OMAP_DSS_GFX));
 211	SR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
 212	SR(OVL_ROW_INC(OMAP_DSS_GFX));
 213	SR(OVL_PIXEL_INC(OMAP_DSS_GFX));
 214	SR(OVL_WINDOW_SKIP(OMAP_DSS_GFX));
 215	SR(OVL_TABLE_BA(OMAP_DSS_GFX));
 216
 217	SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
 218	SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
 219	SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 220
 221	if (dss_has_feature(FEAT_CPR)) {
 222		SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
 223		SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
 224		SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
 225	}
 226	if (dss_has_feature(FEAT_MGR_LCD2)) {
 227		if (dss_has_feature(FEAT_CPR)) {
 228			SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
 229			SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
 230			SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
 231		}
 232
 233		SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
 234		SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
 235		SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
 236	}
 237
 238	if (dss_has_feature(FEAT_PRELOAD))
 239		SR(OVL_PRELOAD(OMAP_DSS_GFX));
 240
 241	/* VID1 */
 242	SR(OVL_BA0(OMAP_DSS_VIDEO1));
 243	SR(OVL_BA1(OMAP_DSS_VIDEO1));
 244	SR(OVL_POSITION(OMAP_DSS_VIDEO1));
 245	SR(OVL_SIZE(OMAP_DSS_VIDEO1));
 246	SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
 247	SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
 248	SR(OVL_ROW_INC(OMAP_DSS_VIDEO1));
 249	SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
 250	SR(OVL_FIR(OMAP_DSS_VIDEO1));
 251	SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
 252	SR(OVL_ACCU0(OMAP_DSS_VIDEO1));
 253	SR(OVL_ACCU1(OMAP_DSS_VIDEO1));
 254
 255	for (i = 0; i < 8; i++)
 256		SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i));
 257
 258	for (i = 0; i < 8; i++)
 259		SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i));
 260
 261	for (i = 0; i < 5; i++)
 262		SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
 263
 264	if (dss_has_feature(FEAT_FIR_COEF_V)) {
 265		for (i = 0; i < 8; i++)
 266			SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
 267	}
 268
 269	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 270		SR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
 271		SR(OVL_BA1_UV(OMAP_DSS_VIDEO1));
 272		SR(OVL_FIR2(OMAP_DSS_VIDEO1));
 273		SR(OVL_ACCU2_0(OMAP_DSS_VIDEO1));
 274		SR(OVL_ACCU2_1(OMAP_DSS_VIDEO1));
 275
 276		for (i = 0; i < 8; i++)
 277			SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i));
 278
 279		for (i = 0; i < 8; i++)
 280			SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i));
 281
 282		for (i = 0; i < 8; i++)
 283			SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i));
 284	}
 285	if (dss_has_feature(FEAT_ATTR2))
 286		SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
 287
 288	if (dss_has_feature(FEAT_PRELOAD))
 289		SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
 290
 291	/* VID2 */
 292	SR(OVL_BA0(OMAP_DSS_VIDEO2));
 293	SR(OVL_BA1(OMAP_DSS_VIDEO2));
 294	SR(OVL_POSITION(OMAP_DSS_VIDEO2));
 295	SR(OVL_SIZE(OMAP_DSS_VIDEO2));
 296	SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
 297	SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
 298	SR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
 299	SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
 300	SR(OVL_FIR(OMAP_DSS_VIDEO2));
 301	SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
 302	SR(OVL_ACCU0(OMAP_DSS_VIDEO2));
 303	SR(OVL_ACCU1(OMAP_DSS_VIDEO2));
 304
 305	for (i = 0; i < 8; i++)
 306		SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i));
 307
 308	for (i = 0; i < 8; i++)
 309		SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i));
 310
 311	for (i = 0; i < 5; i++)
 312		SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
 313
 314	if (dss_has_feature(FEAT_FIR_COEF_V)) {
 315		for (i = 0; i < 8; i++)
 316			SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
 317	}
 318
 319	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 320		SR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
 321		SR(OVL_BA1_UV(OMAP_DSS_VIDEO2));
 322		SR(OVL_FIR2(OMAP_DSS_VIDEO2));
 323		SR(OVL_ACCU2_0(OMAP_DSS_VIDEO2));
 324		SR(OVL_ACCU2_1(OMAP_DSS_VIDEO2));
 325
 326		for (i = 0; i < 8; i++)
 327			SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i));
 328
 329		for (i = 0; i < 8; i++)
 330			SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i));
 331
 332		for (i = 0; i < 8; i++)
 333			SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i));
 334	}
 335	if (dss_has_feature(FEAT_ATTR2))
 336		SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 337
 338	if (dss_has_feature(FEAT_PRELOAD))
 339		SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
 340
 341	if (dss_has_feature(FEAT_CORE_CLK_DIV))
 342		SR(DIVISOR);
 343
 344	dispc.ctx_loss_cnt = dispc_get_ctx_loss_count();
 345	dispc.ctx_valid = true;
 346
 347	DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
 348}
 349
 350static void dispc_restore_context(void)
 351{
 352	int i, ctx;
 353
 354	DSSDBG("dispc_restore_context\n");
 355
 356	if (!dispc.ctx_valid)
 357		return;
 358
 359	ctx = dispc_get_ctx_loss_count();
 360
 361	if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
 362		return;
 363
 364	DSSDBG("ctx_loss_count: saved %d, current %d\n",
 365			dispc.ctx_loss_cnt, ctx);
 366
 367	/*RR(IRQENABLE);*/
 368	/*RR(CONTROL);*/
 369	RR(CONFIG);
 370	RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
 371	RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
 372	RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
 373	RR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
 374	RR(LINE_NUMBER);
 375	RR(TIMING_H(OMAP_DSS_CHANNEL_LCD));
 376	RR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
 377	RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
 378	RR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
 379	if (dss_has_feature(FEAT_GLOBAL_ALPHA))
 380		RR(GLOBAL_ALPHA);
 381	RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
 382	RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
 383	if (dss_has_feature(FEAT_MGR_LCD2)) {
 384		RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
 385		RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
 386		RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
 387		RR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
 388		RR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
 389		RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
 390		RR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
 391		RR(CONFIG2);
 392	}
 393
 394	RR(OVL_BA0(OMAP_DSS_GFX));
 395	RR(OVL_BA1(OMAP_DSS_GFX));
 396	RR(OVL_POSITION(OMAP_DSS_GFX));
 397	RR(OVL_SIZE(OMAP_DSS_GFX));
 398	RR(OVL_ATTRIBUTES(OMAP_DSS_GFX));
 399	RR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
 400	RR(OVL_ROW_INC(OMAP_DSS_GFX));
 401	RR(OVL_PIXEL_INC(OMAP_DSS_GFX));
 402	RR(OVL_WINDOW_SKIP(OMAP_DSS_GFX));
 403	RR(OVL_TABLE_BA(OMAP_DSS_GFX));
 404
 405
 406	RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
 407	RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
 408	RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 409
 410	if (dss_has_feature(FEAT_CPR)) {
 411		RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
 412		RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
 413		RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
 414	}
 415	if (dss_has_feature(FEAT_MGR_LCD2)) {
 416		RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
 417		RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
 418		RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
 419
 420		if (dss_has_feature(FEAT_CPR)) {
 421			RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
 422			RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
 423			RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
 424		}
 425	}
 426
 427	if (dss_has_feature(FEAT_PRELOAD))
 428		RR(OVL_PRELOAD(OMAP_DSS_GFX));
 429
 430	/* VID1 */
 431	RR(OVL_BA0(OMAP_DSS_VIDEO1));
 432	RR(OVL_BA1(OMAP_DSS_VIDEO1));
 433	RR(OVL_POSITION(OMAP_DSS_VIDEO1));
 434	RR(OVL_SIZE(OMAP_DSS_VIDEO1));
 435	RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
 436	RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
 437	RR(OVL_ROW_INC(OMAP_DSS_VIDEO1));
 438	RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
 439	RR(OVL_FIR(OMAP_DSS_VIDEO1));
 440	RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
 441	RR(OVL_ACCU0(OMAP_DSS_VIDEO1));
 442	RR(OVL_ACCU1(OMAP_DSS_VIDEO1));
 443
 444	for (i = 0; i < 8; i++)
 445		RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i));
 446
 447	for (i = 0; i < 8; i++)
 448		RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i));
 449
 450	for (i = 0; i < 5; i++)
 451		RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
 452
 453	if (dss_has_feature(FEAT_FIR_COEF_V)) {
 454		for (i = 0; i < 8; i++)
 455			RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
 456	}
 457
 458	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 459		RR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
 460		RR(OVL_BA1_UV(OMAP_DSS_VIDEO1));
 461		RR(OVL_FIR2(OMAP_DSS_VIDEO1));
 462		RR(OVL_ACCU2_0(OMAP_DSS_VIDEO1));
 463		RR(OVL_ACCU2_1(OMAP_DSS_VIDEO1));
 464
 465		for (i = 0; i < 8; i++)
 466			RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i));
 467
 468		for (i = 0; i < 8; i++)
 469			RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i));
 470
 471		for (i = 0; i < 8; i++)
 472			RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i));
 473	}
 474	if (dss_has_feature(FEAT_ATTR2))
 475		RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
 476
 477	if (dss_has_feature(FEAT_PRELOAD))
 478		RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
 479
 480	/* VID2 */
 481	RR(OVL_BA0(OMAP_DSS_VIDEO2));
 482	RR(OVL_BA1(OMAP_DSS_VIDEO2));
 483	RR(OVL_POSITION(OMAP_DSS_VIDEO2));
 484	RR(OVL_SIZE(OMAP_DSS_VIDEO2));
 485	RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
 486	RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
 487	RR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
 488	RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
 489	RR(OVL_FIR(OMAP_DSS_VIDEO2));
 490	RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
 491	RR(OVL_ACCU0(OMAP_DSS_VIDEO2));
 492	RR(OVL_ACCU1(OMAP_DSS_VIDEO2));
 493
 494	for (i = 0; i < 8; i++)
 495		RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i));
 496
 497	for (i = 0; i < 8; i++)
 498		RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i));
 499
 500	for (i = 0; i < 5; i++)
 501		RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
 502
 503	if (dss_has_feature(FEAT_FIR_COEF_V)) {
 504		for (i = 0; i < 8; i++)
 505			RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
 506	}
 507
 508	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 509		RR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
 510		RR(OVL_BA1_UV(OMAP_DSS_VIDEO2));
 511		RR(OVL_FIR2(OMAP_DSS_VIDEO2));
 512		RR(OVL_ACCU2_0(OMAP_DSS_VIDEO2));
 513		RR(OVL_ACCU2_1(OMAP_DSS_VIDEO2));
 514
 515		for (i = 0; i < 8; i++)
 516			RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i));
 517
 518		for (i = 0; i < 8; i++)
 519			RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i));
 520
 521		for (i = 0; i < 8; i++)
 522			RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i));
 523	}
 524	if (dss_has_feature(FEAT_ATTR2))
 525		RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 526
 527	if (dss_has_feature(FEAT_PRELOAD))
 528		RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
 529
 530	if (dss_has_feature(FEAT_CORE_CLK_DIV))
 531		RR(DIVISOR);
 532
 533	/* enable last, because LCD & DIGIT enable are here */
 534	RR(CONTROL);
 535	if (dss_has_feature(FEAT_MGR_LCD2))
 536		RR(CONTROL2);
 537	/* clear spurious SYNC_LOST_DIGIT interrupts */
 538	dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
 539
 540	/*
 541	 * enable last so IRQs won't trigger before
 542	 * the context is fully restored
 543	 */
 544	RR(IRQENABLE);
 545
 546	DSSDBG("context restored\n");
 547}
 548
 549#undef SR
 550#undef RR
 551
 552int dispc_runtime_get(void)
 553{
 554	int r;
 555
 556	DSSDBG("dispc_runtime_get\n");
 557
 558	r = pm_runtime_get_sync(&dispc.pdev->dev);
 559	WARN_ON(r < 0);
 560	return r < 0 ? r : 0;
 561}
 562
 563void dispc_runtime_put(void)
 564{
 565	int r;
 566
 567	DSSDBG("dispc_runtime_put\n");
 568
 569	r = pm_runtime_put(&dispc.pdev->dev);
 570	WARN_ON(r < 0);
 571}
 572
 573
 574bool dispc_go_busy(enum omap_channel channel)
 575{
 576	int bit;
 577
 578	if (channel == OMAP_DSS_CHANNEL_LCD ||
 579			channel == OMAP_DSS_CHANNEL_LCD2)
 580		bit = 5; /* GOLCD */
 581	else
 582		bit = 6; /* GODIGIT */
 583
 584	if (channel == OMAP_DSS_CHANNEL_LCD2)
 585		return REG_GET(DISPC_CONTROL2, bit, bit) == 1;
 586	else
 587		return REG_GET(DISPC_CONTROL, bit, bit) == 1;
 588}
 589
 590void dispc_go(enum omap_channel channel)
 591{
 592	int bit;
 593	bool enable_bit, go_bit;
 594
 595	if (channel == OMAP_DSS_CHANNEL_LCD ||
 596			channel == OMAP_DSS_CHANNEL_LCD2)
 597		bit = 0; /* LCDENABLE */
 598	else
 599		bit = 1; /* DIGITALENABLE */
 600
 601	/* if the channel is not enabled, we don't need GO */
 602	if (channel == OMAP_DSS_CHANNEL_LCD2)
 603		enable_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1;
 604	else
 605		enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
 606
 607	if (!enable_bit)
 608		return;
 609
 610	if (channel == OMAP_DSS_CHANNEL_LCD ||
 611			channel == OMAP_DSS_CHANNEL_LCD2)
 612		bit = 5; /* GOLCD */
 613	else
 614		bit = 6; /* GODIGIT */
 615
 616	if (channel == OMAP_DSS_CHANNEL_LCD2)
 617		go_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1;
 618	else
 619		go_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
 620
 621	if (go_bit) {
 622		DSSERR("GO bit not down for channel %d\n", channel);
 623		return;
 624	}
 625
 626	DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" :
 627		(channel == OMAP_DSS_CHANNEL_LCD2 ? "LCD2" : "DIGIT"));
 628
 629	if (channel == OMAP_DSS_CHANNEL_LCD2)
 630		REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit);
 631	else
 632		REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
 633}
 634
 635static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
 636{
 637	dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
 638}
 639
 640static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
 641{
 642	dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value);
 643}
 644
 645static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
 646{
 647	dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value);
 648}
 649
 650static void _dispc_write_firh2_reg(enum omap_plane plane, int reg, u32 value)
 651{
 652	BUG_ON(plane == OMAP_DSS_GFX);
 653
 654	dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value);
 655}
 656
 657static void _dispc_write_firhv2_reg(enum omap_plane plane, int reg, u32 value)
 658{
 659	BUG_ON(plane == OMAP_DSS_GFX);
 660
 661	dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value);
 662}
 663
 664static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
 665{
 666	BUG_ON(plane == OMAP_DSS_GFX);
 667
 668	dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);
 669}
 670
 671static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
 672				  int vscaleup, int five_taps,
 673				  enum omap_color_component color_comp)
 674{
 675	/* Coefficients for horizontal up-sampling */
 676	static const struct dispc_h_coef coef_hup[8] = {
 677		{  0,   0, 128,   0,  0 },
 678		{ -1,  13, 124,  -8,  0 },
 679		{ -2,  30, 112, -11, -1 },
 680		{ -5,  51,  95, -11, -2 },
 681		{  0,  -9,  73,  73, -9 },
 682		{ -2, -11,  95,  51, -5 },
 683		{ -1, -11, 112,  30, -2 },
 684		{  0,  -8, 124,  13, -1 },
 685	};
 686
 687	/* Coefficients for vertical up-sampling */
 688	static const struct dispc_v_coef coef_vup_3tap[8] = {
 689		{ 0,  0, 128,  0, 0 },
 690		{ 0,  3, 123,  2, 0 },
 691		{ 0, 12, 111,  5, 0 },
 692		{ 0, 32,  89,  7, 0 },
 693		{ 0,  0,  64, 64, 0 },
 694		{ 0,  7,  89, 32, 0 },
 695		{ 0,  5, 111, 12, 0 },
 696		{ 0,  2, 123,  3, 0 },
 697	};
 698
 699	static const struct dispc_v_coef coef_vup_5tap[8] = {
 700		{  0,   0, 128,   0,  0 },
 701		{ -1,  13, 124,  -8,  0 },
 702		{ -2,  30, 112, -11, -1 },
 703		{ -5,  51,  95, -11, -2 },
 704		{  0,  -9,  73,  73, -9 },
 705		{ -2, -11,  95,  51, -5 },
 706		{ -1, -11, 112,  30, -2 },
 707		{  0,  -8, 124,  13, -1 },
 708	};
 709
 710	/* Coefficients for horizontal down-sampling */
 711	static const struct dispc_h_coef coef_hdown[8] = {
 712		{   0, 36, 56, 36,  0 },
 713		{   4, 40, 55, 31, -2 },
 714		{   8, 44, 54, 27, -5 },
 715		{  12, 48, 53, 22, -7 },
 716		{  -9, 17, 52, 51, 17 },
 717		{  -7, 22, 53, 48, 12 },
 718		{  -5, 27, 54, 44,  8 },
 719		{  -2, 31, 55, 40,  4 },
 720	};
 721
 722	/* Coefficients for vertical down-sampling */
 723	static const struct dispc_v_coef coef_vdown_3tap[8] = {
 724		{ 0, 36, 56, 36, 0 },
 725		{ 0, 40, 57, 31, 0 },
 726		{ 0, 45, 56, 27, 0 },
 727		{ 0, 50, 55, 23, 0 },
 728		{ 0, 18, 55, 55, 0 },
 729		{ 0, 23, 55, 50, 0 },
 730		{ 0, 27, 56, 45, 0 },
 731		{ 0, 31, 57, 40, 0 },
 732	};
 733
 734	static const struct dispc_v_coef coef_vdown_5tap[8] = {
 735		{   0, 36, 56, 36,  0 },
 736		{   4, 40, 55, 31, -2 },
 737		{   8, 44, 54, 27, -5 },
 738		{  12, 48, 53, 22, -7 },
 739		{  -9, 17, 52, 51, 17 },
 740		{  -7, 22, 53, 48, 12 },
 741		{  -5, 27, 54, 44,  8 },
 742		{  -2, 31, 55, 40,  4 },
 743	};
 744
 745	const struct dispc_h_coef *h_coef;
 746	const struct dispc_v_coef *v_coef;
 747	int i;
 748
 749	if (hscaleup)
 750		h_coef = coef_hup;
 751	else
 752		h_coef = coef_hdown;
 753
 754	if (vscaleup)
 755		v_coef = five_taps ? coef_vup_5tap : coef_vup_3tap;
 756	else
 757		v_coef = five_taps ? coef_vdown_5tap : coef_vdown_3tap;
 758
 759	for (i = 0; i < 8; i++) {
 760		u32 h, hv;
 761
 762		h = FLD_VAL(h_coef[i].hc0, 7, 0)
 763			| FLD_VAL(h_coef[i].hc1, 15, 8)
 764			| FLD_VAL(h_coef[i].hc2, 23, 16)
 765			| FLD_VAL(h_coef[i].hc3, 31, 24);
 766		hv = FLD_VAL(h_coef[i].hc4, 7, 0)
 767			| FLD_VAL(v_coef[i].vc0, 15, 8)
 768			| FLD_VAL(v_coef[i].vc1, 23, 16)
 769			| FLD_VAL(v_coef[i].vc2, 31, 24);
 770
 771		if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
 772			_dispc_write_firh_reg(plane, i, h);
 773			_dispc_write_firhv_reg(plane, i, hv);
 774		} else {
 775			_dispc_write_firh2_reg(plane, i, h);
 776			_dispc_write_firhv2_reg(plane, i, hv);
 777		}
 778
 779	}
 780
 781	if (five_taps) {
 782		for (i = 0; i < 8; i++) {
 783			u32 v;
 784			v = FLD_VAL(v_coef[i].vc00, 7, 0)
 785				| FLD_VAL(v_coef[i].vc22, 15, 8);
 786			if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
 787				_dispc_write_firv_reg(plane, i, v);
 788			else
 789				_dispc_write_firv2_reg(plane, i, v);
 790		}
 791	}
 792}
 793
 794static void _dispc_setup_color_conv_coef(void)
 795{
 796	const struct color_conv_coef {
 797		int  ry,  rcr,  rcb,   gy,  gcr,  gcb,   by,  bcr,  bcb;
 798		int  full_range;
 799	}  ctbl_bt601_5 = {
 800		298,  409,    0,  298, -208, -100,  298,    0,  517, 0,
 801	};
 802
 803	const struct color_conv_coef *ct;
 804
 805#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
 806
 807	ct = &ctbl_bt601_5;
 808
 809	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0),
 810		CVAL(ct->rcr, ct->ry));
 811	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1),
 812		CVAL(ct->gy,  ct->rcb));
 813	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2),
 814		CVAL(ct->gcb, ct->gcr));
 815	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3),
 816		CVAL(ct->bcr, ct->by));
 817	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4),
 818		CVAL(0, ct->bcb));
 819
 820	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0),
 821		CVAL(ct->rcr, ct->ry));
 822	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1),
 823		CVAL(ct->gy, ct->rcb));
 824	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2),
 825		CVAL(ct->gcb, ct->gcr));
 826	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3),
 827		CVAL(ct->bcr, ct->by));
 828	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4),
 829		CVAL(0, ct->bcb));
 830
 831#undef CVAL
 832
 833	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1),
 834		ct->full_range, 11, 11);
 835	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2),
 836		ct->full_range, 11, 11);
 837}
 838
 839
 840static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
 841{
 842	dispc_write_reg(DISPC_OVL_BA0(plane), paddr);
 843}
 844
 845static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
 846{
 847	dispc_write_reg(DISPC_OVL_BA1(plane), paddr);
 848}
 849
 850static void _dispc_set_plane_ba0_uv(enum omap_plane plane, u32 paddr)
 851{
 852	dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr);
 853}
 854
 855static void _dispc_set_plane_ba1_uv(enum omap_plane plane, u32 paddr)
 856{
 857	dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
 858}
 859
 860static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
 861{
 862	u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
 863
 864	dispc_write_reg(DISPC_OVL_POSITION(plane), val);
 865}
 866
 867static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
 868{
 869	u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
 870
 871	if (plane == OMAP_DSS_GFX)
 872		dispc_write_reg(DISPC_OVL_SIZE(plane), val);
 873	else
 874		dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
 875}
 876
 877static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
 878{
 879	u32 val;
 880
 881	BUG_ON(plane == OMAP_DSS_GFX);
 882
 883	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
 884
 885	dispc_write_reg(DISPC_OVL_SIZE(plane), val);
 886}
 887
 888static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable)
 889{
 890	if (!dss_has_feature(FEAT_PRE_MULT_ALPHA))
 891		return;
 892
 893	if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
 894		plane == OMAP_DSS_VIDEO1)
 895		return;
 896
 897	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
 898}
 899
 900static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
 901{
 902	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
 903		return;
 904
 905	if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
 906		plane == OMAP_DSS_VIDEO1)
 907		return;
 908
 909	if (plane == OMAP_DSS_GFX)
 910		REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
 911	else if (plane == OMAP_DSS_VIDEO2)
 912		REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
 913}
 914
 915static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
 916{
 917	dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc);
 918}
 919
 920static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
 921{
 922	dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc);
 923}
 924
 925static void _dispc_set_color_mode(enum omap_plane plane,
 926		enum omap_color_mode color_mode)
 927{
 928	u32 m = 0;
 929	if (plane != OMAP_DSS_GFX) {
 930		switch (color_mode) {
 931		case OMAP_DSS_COLOR_NV12:
 932			m = 0x0; break;
 933		case OMAP_DSS_COLOR_RGB12U:
 934			m = 0x1; break;
 935		case OMAP_DSS_COLOR_RGBA16:
 936			m = 0x2; break;
 937		case OMAP_DSS_COLOR_RGBX16:
 938			m = 0x4; break;
 939		case OMAP_DSS_COLOR_ARGB16:
 940			m = 0x5; break;
 941		case OMAP_DSS_COLOR_RGB16:
 942			m = 0x6; break;
 943		case OMAP_DSS_COLOR_ARGB16_1555:
 944			m = 0x7; break;
 945		case OMAP_DSS_COLOR_RGB24U:
 946			m = 0x8; break;
 947		case OMAP_DSS_COLOR_RGB24P:
 948			m = 0x9; break;
 949		case OMAP_DSS_COLOR_YUV2:
 950			m = 0xa; break;
 951		case OMAP_DSS_COLOR_UYVY:
 952			m = 0xb; break;
 953		case OMAP_DSS_COLOR_ARGB32:
 954			m = 0xc; break;
 955		case OMAP_DSS_COLOR_RGBA32:
 956			m = 0xd; break;
 957		case OMAP_DSS_COLOR_RGBX32:
 958			m = 0xe; break;
 959		case OMAP_DSS_COLOR_XRGB16_1555:
 960			m = 0xf; break;
 961		default:
 962			BUG(); break;
 963		}
 964	} else {
 965		switch (color_mode) {
 966		case OMAP_DSS_COLOR_CLUT1:
 967			m = 0x0; break;
 968		case OMAP_DSS_COLOR_CLUT2:
 969			m = 0x1; break;
 970		case OMAP_DSS_COLOR_CLUT4:
 971			m = 0x2; break;
 972		case OMAP_DSS_COLOR_CLUT8:
 973			m = 0x3; break;
 974		case OMAP_DSS_COLOR_RGB12U:
 975			m = 0x4; break;
 976		case OMAP_DSS_COLOR_ARGB16:
 977			m = 0x5; break;
 978		case OMAP_DSS_COLOR_RGB16:
 979			m = 0x6; break;
 980		case OMAP_DSS_COLOR_ARGB16_1555:
 981			m = 0x7; break;
 982		case OMAP_DSS_COLOR_RGB24U:
 983			m = 0x8; break;
 984		case OMAP_DSS_COLOR_RGB24P:
 985			m = 0x9; break;
 986		case OMAP_DSS_COLOR_YUV2:
 987			m = 0xa; break;
 988		case OMAP_DSS_COLOR_UYVY:
 989			m = 0xb; break;
 990		case OMAP_DSS_COLOR_ARGB32:
 991			m = 0xc; break;
 992		case OMAP_DSS_COLOR_RGBA32:
 993			m = 0xd; break;
 994		case OMAP_DSS_COLOR_RGBX32:
 995			m = 0xe; break;
 996		case OMAP_DSS_COLOR_XRGB16_1555:
 997			m = 0xf; break;
 998		default:
 999			BUG(); break;
1000		}
1001	}
1002
1003	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
1004}
1005
1006void dispc_set_channel_out(enum omap_plane plane,
1007		enum omap_channel channel)
1008{
1009	int shift;
1010	u32 val;
1011	int chan = 0, chan2 = 0;
1012
1013	switch (plane) {
1014	case OMAP_DSS_GFX:
1015		shift = 8;
1016		break;
1017	case OMAP_DSS_VIDEO1:
1018	case OMAP_DSS_VIDEO2:
1019		shift = 16;
1020		break;
1021	default:
1022		BUG();
1023		return;
1024	}
1025
1026	val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
1027	if (dss_has_feature(FEAT_MGR_LCD2)) {
1028		switch (channel) {
1029		case OMAP_DSS_CHANNEL_LCD:
1030			chan = 0;
1031			chan2 = 0;
1032			break;
1033		case OMAP_DSS_CHANNEL_DIGIT:
1034			chan = 1;
1035			chan2 = 0;
1036			break;
1037		case OMAP_DSS_CHANNEL_LCD2:
1038			chan = 0;
1039			chan2 = 1;
1040			break;
1041		default:
1042			BUG();
1043		}
1044
1045		val = FLD_MOD(val, chan, shift, shift);
1046		val = FLD_MOD(val, chan2, 31, 30);
1047	} else {
1048		val = FLD_MOD(val, channel, shift, shift);
1049	}
1050	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
1051}
1052
1053static void dispc_set_burst_size(enum omap_plane plane,
1054		enum omap_burst_size burst_size)
1055{
1056	int shift;
1057
1058	switch (plane) {
1059	case OMAP_DSS_GFX:
1060		shift = 6;
1061		break;
1062	case OMAP_DSS_VIDEO1:
1063	case OMAP_DSS_VIDEO2:
1064		shift = 14;
1065		break;
1066	default:
1067		BUG();
1068		return;
1069	}
1070
1071	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift);
1072}
1073
1074static void dispc_configure_burst_sizes(void)
1075{
1076	int i;
1077	const int burst_size = BURST_SIZE_X8;
1078
1079	/* Configure burst size always to maximum size */
1080	for (i = 0; i < omap_dss_get_num_overlays(); ++i)
1081		dispc_set_burst_size(i, burst_size);
1082}
1083
1084u32 dispc_get_burst_size(enum omap_plane plane)
1085{
1086	unsigned unit = dss_feat_get_burst_size_unit();
1087	/* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
1088	return unit * 8;
1089}
1090
1091void dispc_enable_gamma_table(bool enable)
1092{
1093	/*
1094	 * This is partially implemented to support only disabling of
1095	 * the gamma table.
1096	 */
1097	if (enable) {
1098		DSSWARN("Gamma table enabling for TV not yet supported");
1099		return;
1100	}
1101
1102	REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
1103}
1104
1105void dispc_enable_cpr(enum omap_channel channel, bool enable)
1106{
1107	u16 reg;
1108
1109	if (channel == OMAP_DSS_CHANNEL_LCD)
1110		reg = DISPC_CONFIG;
1111	else if (channel == OMAP_DSS_CHANNEL_LCD2)
1112		reg = DISPC_CONFIG2;
1113	else
1114		return;
1115
1116	REG_FLD_MOD(reg, enable, 15, 15);
1117}
1118
1119void dispc_set_cpr_coef(enum omap_channel channel,
1120		struct omap_dss_cpr_coefs *coefs)
1121{
1122	u32 coef_r, coef_g, coef_b;
1123
1124	if (channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2)
1125		return;
1126
1127	coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) |
1128		FLD_VAL(coefs->rb, 9, 0);
1129	coef_g = FLD_VAL(coefs->gr, 31, 22) | FLD_VAL(coefs->gg, 20, 11) |
1130		FLD_VAL(coefs->gb, 9, 0);
1131	coef_b = FLD_VAL(coefs->br, 31, 22) | FLD_VAL(coefs->bg, 20, 11) |
1132		FLD_VAL(coefs->bb, 9, 0);
1133
1134	dispc_write_reg(DISPC_CPR_COEF_R(channel), coef_r);
1135	dispc_write_reg(DISPC_CPR_COEF_G(channel), coef_g);
1136	dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b);
1137}
1138
1139static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
1140{
1141	u32 val;
1142
1143	BUG_ON(plane == OMAP_DSS_GFX);
1144
1145	val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
1146	val = FLD_MOD(val, enable, 9, 9);
1147	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
1148}
1149
1150void dispc_enable_replication(enum omap_plane plane, bool enable)
1151{
1152	int bit;
1153
1154	if (plane == OMAP_DSS_GFX)
1155		bit = 5;
1156	else
1157		bit = 10;
1158
1159	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
1160}
1161
1162void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
1163{
1164	u32 val;
1165	BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
1166	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
1167	dispc_write_reg(DISPC_SIZE_MGR(channel), val);
1168}
1169
1170void dispc_set_digit_size(u16 width, u16 height)
1171{
1172	u32 val;
1173	BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
1174	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
1175	dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
1176}
1177
1178static void dispc_read_plane_fifo_sizes(void)
1179{
1180	u32 size;
1181	int plane;
1182	u8 start, end;
1183	u32 unit;
1184
1185	unit = dss_feat_get_buffer_size_unit();
1186
1187	dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
1188
1189	for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
1190		size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end);
1191		size *= unit;
1192		dispc.fifo_size[plane] = size;
1193	}
1194}
1195
1196u32 dispc_get_plane_fifo_size(enum omap_plane plane)
1197{
1198	return dispc.fifo_size[plane];
1199}
1200
1201void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
1202{
1203	u8 hi_start, hi_end, lo_start, lo_end;
1204	u32 unit;
1205
1206	unit = dss_feat_get_buffer_size_unit();
1207
1208	WARN_ON(low % unit != 0);
1209	WARN_ON(high % unit != 0);
1210
1211	low /= unit;
1212	high /= unit;
1213
1214	dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
1215	dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
1216
1217	DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
1218			plane,
1219			REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
1220				lo_start, lo_end),
1221			REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
1222				hi_start, hi_end),
1223			low, high);
1224
1225	dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
1226			FLD_VAL(high, hi_start, hi_end) |
1227			FLD_VAL(low, lo_start, lo_end));
1228}
1229
1230void dispc_enable_fifomerge(bool enable)
1231{
1232	DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
1233	REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
1234}
1235
1236static void _dispc_set_fir(enum omap_plane plane,
1237				int hinc, int vinc,
1238				enum omap_color_component color_comp)
1239{
1240	u32 val;
1241
1242	if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
1243		u8 hinc_start, hinc_end, vinc_start, vinc_end;
1244
1245		dss_feat_get_reg_field(FEAT_REG_FIRHINC,
1246					&hinc_start, &hinc_end);
1247		dss_feat_get_reg_field(FEAT_REG_FIRVINC,
1248					&vinc_start, &vinc_end);
1249		val = FLD_VAL(vinc, vinc_start, vinc_end) |
1250				FLD_VAL(hinc, hinc_start, hinc_end);
1251
1252		dispc_write_reg(DISPC_OVL_FIR(plane), val);
1253	} else {
1254		val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
1255		dispc_write_reg(DISPC_OVL_FIR2(plane), val);
1256	}
1257}
1258
1259static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
1260{
1261	u32 val;
1262	u8 hor_start, hor_end, vert_start, vert_end;
1263
1264	dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
1265	dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
1266
1267	val = FLD_VAL(vaccu, vert_start, vert_end) |
1268			FLD_VAL(haccu, hor_start, hor_end);
1269
1270	dispc_write_reg(DISPC_OVL_ACCU0(plane), val);
1271}
1272
1273static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
1274{
1275	u32 val;
1276	u8 hor_start, hor_end, vert_start, vert_end;
1277
1278	dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
1279	dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
1280
1281	val = FLD_VAL(vaccu, vert_start, vert_end) |
1282			FLD_VAL(haccu, hor_start, hor_end);
1283
1284	dispc_write_reg(DISPC_OVL_ACCU1(plane), val);
1285}
1286
1287static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu)
1288{
1289	u32 val;
1290
1291	val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
1292	dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val);
1293}
1294
1295static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu)
1296{
1297	u32 val;
1298
1299	val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
1300	dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val);
1301}
1302
1303static void _dispc_set_scale_param(enum omap_plane plane,
1304		u16 orig_width, u16 orig_height,
1305		u16 out_width, u16 out_height,
1306		bool five_taps, u8 rotation,
1307		enum omap_color_component color_comp)
1308{
1309	int fir_hinc, fir_vinc;
1310	int hscaleup, vscaleup;
1311
1312	hscaleup = orig_width <= out_width;
1313	vscaleup = orig_height <= out_height;
1314
1315	_dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps, color_comp);
1316
1317	fir_hinc = 1024 * orig_width / out_width;
1318	fir_vinc = 1024 * orig_height / out_height;
1319
1320	_dispc_set_fir(plane, fir_hinc, fir_vinc, color_comp);
1321}
1322
1323static void _dispc_set_scaling_common(enum omap_plane plane,
1324		u16 orig_width, u16 orig_height,
1325		u16 out_width, u16 out_height,
1326		bool ilace, bool five_taps,
1327		bool fieldmode, enum omap_color_mode color_mode,
1328		u8 rotation)
1329{
1330	int accu0 = 0;
1331	int accu1 = 0;
1332	u32 l;
1333
1334	_dispc_set_scale_param(plane, orig_width, orig_height,
1335				out_width, out_height, five_taps,
1336				rotation, DISPC_COLOR_COMPONENT_RGB_Y);
1337	l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
1338
1339	/* RESIZEENABLE and VERTICALTAPS */
1340	l &= ~((0x3 << 5) | (0x1 << 21));
1341	l |= (orig_width != out_width) ? (1 << 5) : 0;
1342	l |= (orig_height != out_height) ? (1 << 6) : 0;
1343	l |= five_taps ? (1 << 21) : 0;
1344
1345	/* VRESIZECONF and HRESIZECONF */
1346	if (dss_has_feature(FEAT_RESIZECONF)) {
1347		l &= ~(0x3 << 7);
1348		l |= (orig_width <= out_width) ? 0 : (1 << 7);
1349		l |= (orig_height <= out_height) ? 0 : (1 << 8);
1350	}
1351
1352	/* LINEBUFFERSPLIT */
1353	if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) {
1354		l &= ~(0x1 << 22);
1355		l |= five_taps ? (1 << 22) : 0;
1356	}
1357
1358	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
1359
1360	/*
1361	 * field 0 = even field = bottom field
1362	 * field 1 = odd field = top field
1363	 */
1364	if (ilace && !fieldmode) {
1365		accu1 = 0;
1366		accu0 = ((1024 * orig_height / out_height) / 2) & 0x3ff;
1367		if (accu0 >= 1024/2) {
1368			accu1 = 1024/2;
1369			accu0 -= accu1;
1370		}
1371	}
1372
1373	_dispc_set_vid_accu0(plane, 0, accu0);
1374	_dispc_set_vid_accu1(plane, 0, accu1);
1375}
1376
1377static void _dispc_set_scaling_uv(enum omap_plane plane,
1378		u16 orig_width, u16 orig_height,
1379		u16 out_width, u16 out_height,
1380		bool ilace, bool five_taps,
1381		bool fieldmode, enum omap_color_mode color_mode,
1382		u8 rotation)
1383{
1384	int scale_x = out_width != orig_width;
1385	int scale_y = out_height != orig_height;
1386
1387	if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
1388		return;
1389	if ((color_mode != OMAP_DSS_COLOR_YUV2 &&
1390			color_mode != OMAP_DSS_COLOR_UYVY &&
1391			color_mode != OMAP_DSS_COLOR_NV12)) {
1392		/* reset chroma resampling for RGB formats  */
1393		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
1394		return;
1395	}
1396	switch (color_mode) {
1397	case OMAP_DSS_COLOR_NV12:
1398		/* UV is subsampled by 2 vertically*/
1399		orig_height >>= 1;
1400		/* UV is subsampled by 2 horz.*/
1401		orig_width >>= 1;
1402		break;
1403	case OMAP_DSS_COLOR_YUV2:
1404	case OMAP_DSS_COLOR_UYVY:
1405		/*For YUV422 with 90/270 rotation,
1406		 *we don't upsample chroma
1407		 */
1408		if (rotation == OMAP_DSS_ROT_0 ||
1409			rotation == OMAP_DSS_ROT_180)
1410			/* UV is subsampled by 2 hrz*/
1411			orig_width >>= 1;
1412		/* must use FIR for YUV422 if rotated */
1413		if (rotation != OMAP_DSS_ROT_0)
1414			scale_x = scale_y = true;
1415		break;
1416	default:
1417		BUG();
1418	}
1419
1420	if (out_width != orig_width)
1421		scale_x = true;
1422	if (out_height != orig_height)
1423		scale_y = true;
1424
1425	_dispc_set_scale_param(plane, orig_width, orig_height,
1426			out_width, out_height, five_taps,
1427				rotation, DISPC_COLOR_COMPONENT_UV);
1428
1429	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
1430		(scale_x || scale_y) ? 1 : 0, 8, 8);
1431	/* set H scaling */
1432	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
1433	/* set V scaling */
1434	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
1435
1436	_dispc_set_vid_accu2_0(plane, 0x80, 0);
1437	_dispc_set_vid_accu2_1(plane, 0x80, 0);
1438}
1439
1440static void _dispc_set_scaling(enum omap_plane plane,
1441		u16 orig_width, u16 orig_height,
1442		u16 out_width, u16 out_height,
1443		bool ilace, bool five_taps,
1444		bool fieldmode, enum omap_color_mode color_mode,
1445		u8 rotation)
1446{
1447	BUG_ON(plane == OMAP_DSS_GFX);
1448
1449	_dispc_set_scaling_common(plane,
1450			orig_width, orig_height,
1451			out_width, out_height,
1452			ilace, five_taps,
1453			fieldmode, color_mode,
1454			rotation);
1455
1456	_dispc_set_scaling_uv(plane,
1457		orig_width, orig_height,
1458		out_width, out_height,
1459		ilace, five_taps,
1460		fieldmode, color_mode,
1461		rotation);
1462}
1463
1464static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
1465		bool mirroring, enum omap_color_mode color_mode)
1466{
1467	bool row_repeat = false;
1468	int vidrot = 0;
1469
1470	if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1471			color_mode == OMAP_DSS_COLOR_UYVY) {
1472
1473		if (mirroring) {
1474			switch (rotation) {
1475			case OMAP_DSS_ROT_0:
1476				vidrot = 2;
1477				break;
1478			case OMAP_DSS_ROT_90:
1479				vidrot = 1;
1480				break;
1481			case OMAP_DSS_ROT_180:
1482				vidrot = 0;
1483				break;
1484			case OMAP_DSS_ROT_270:
1485				vidrot = 3;
1486				break;
1487			}
1488		} else {
1489			switch (rotation) {
1490			case OMAP_DSS_ROT_0:
1491				vidrot = 0;
1492				break;
1493			case OMAP_DSS_ROT_90:
1494				vidrot = 1;
1495				break;
1496			case OMAP_DSS_ROT_180:
1497				vidrot = 2;
1498				break;
1499			case OMAP_DSS_ROT_270:
1500				vidrot = 3;
1501				break;
1502			}
1503		}
1504
1505		if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270)
1506			row_repeat = true;
1507		else
1508			row_repeat = false;
1509	}
1510
1511	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12);
1512	if (dss_has_feature(FEAT_ROWREPEATENABLE))
1513		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane),
1514			row_repeat ? 1 : 0, 18, 18);
1515}
1516
1517static int color_mode_to_bpp(enum omap_color_mode color_mode)
1518{
1519	switch (color_mode) {
1520	case OMAP_DSS_COLOR_CLUT1:
1521		return 1;
1522	case OMAP_DSS_COLOR_CLUT2:
1523		return 2;
1524	case OMAP_DSS_COLOR_CLUT4:
1525		return 4;
1526	case OMAP_DSS_COLOR_CLUT8:
1527	case OMAP_DSS_COLOR_NV12:
1528		return 8;
1529	case OMAP_DSS_COLOR_RGB12U:
1530	case OMAP_DSS_COLOR_RGB16:
1531	case OMAP_DSS_COLOR_ARGB16:
1532	case OMAP_DSS_COLOR_YUV2:
1533	case OMAP_DSS_COLOR_UYVY:
1534	case OMAP_DSS_COLOR_RGBA16:
1535	case OMAP_DSS_COLOR_RGBX16:
1536	case OMAP_DSS_COLOR_ARGB16_1555:
1537	case OMAP_DSS_COLOR_XRGB16_1555:
1538		return 16;
1539	case OMAP_DSS_COLOR_RGB24P:
1540		return 24;
1541	case OMAP_DSS_COLOR_RGB24U:
1542	case OMAP_DSS_COLOR_ARGB32:
1543	case OMAP_DSS_COLOR_RGBA32:
1544	case OMAP_DSS_COLOR_RGBX32:
1545		return 32;
1546	default:
1547		BUG();
1548	}
1549}
1550
1551static s32 pixinc(int pixels, u8 ps)
1552{
1553	if (pixels == 1)
1554		return 1;
1555	else if (pixels > 1)
1556		return 1 + (pixels - 1) * ps;
1557	else if (pixels < 0)
1558		return 1 - (-pixels + 1) * ps;
1559	else
1560		BUG();
1561}
1562
1563static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1564		u16 screen_width,
1565		u16 width, u16 height,
1566		enum omap_color_mode color_mode, bool fieldmode,
1567		unsigned int field_offset,
1568		unsigned *offset0, unsigned *offset1,
1569		s32 *row_inc, s32 *pix_inc)
1570{
1571	u8 ps;
1572
1573	/* FIXME CLUT formats */
1574	switch (color_mode) {
1575	case OMAP_DSS_COLOR_CLUT1:
1576	case OMAP_DSS_COLOR_CLUT2:
1577	case OMAP_DSS_COLOR_CLUT4:
1578	case OMAP_DSS_COLOR_CLUT8:
1579		BUG();
1580		return;
1581	case OMAP_DSS_COLOR_YUV2:
1582	case OMAP_DSS_COLOR_UYVY:
1583		ps = 4;
1584		break;
1585	default:
1586		ps = color_mode_to_bpp(color_mode) / 8;
1587		break;
1588	}
1589
1590	DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
1591			width, height);
1592
1593	/*
1594	 * field 0 = even field = bottom field
1595	 * field 1 = odd field = top field
1596	 */
1597	switch (rotation + mirror * 4) {
1598	case OMAP_DSS_ROT_0:
1599	case OMAP_DSS_ROT_180:
1600		/*
1601		 * If the pixel format is YUV or UYVY divide the width
1602		 * of the image by 2 for 0 and 180 degree rotation.
1603		 */
1604		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1605			color_mode == OMAP_DSS_COLOR_UYVY)
1606			width = width >> 1;
1607	case OMAP_DSS_ROT_90:
1608	case OMAP_DSS_ROT_270:
1609		*offset1 = 0;
1610		if (field_offset)
1611			*offset0 = field_offset * screen_width * ps;
1612		else
1613			*offset0 = 0;
1614
1615		*row_inc = pixinc(1 + (screen_width - width) +
1616				(fieldmode ? screen_width : 0),
1617				ps);
1618		*pix_inc = pixinc(1, ps);
1619		break;
1620
1621	case OMAP_DSS_ROT_0 + 4:
1622	case OMAP_DSS_ROT_180 + 4:
1623		/* If the pixel format is YUV or UYVY divide the width
1624		 * of the image by 2  for 0 degree and 180 degree
1625		 */
1626		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1627			color_mode == OMAP_DSS_COLOR_UYVY)
1628			width = width >> 1;
1629	case OMAP_DSS_ROT_90 + 4:
1630	case OMAP_DSS_ROT_270 + 4:
1631		*offset1 = 0;
1632		if (field_offset)
1633			*offset0 = field_offset * screen_width * ps;
1634		else
1635			*offset0 = 0;
1636		*row_inc = pixinc(1 - (screen_width + width) -
1637				(fieldmode ? screen_width : 0),
1638				ps);
1639		*pix_inc = pixinc(1, ps);
1640		break;
1641
1642	default:
1643		BUG();
1644	}
1645}
1646
1647static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1648		u16 screen_width,
1649		u16 width, u16 height,
1650		enum omap_color_mode color_mode, bool fieldmode,
1651		unsigned int field_offset,
1652		unsigned *offset0, unsigned *offset1,
1653		s32 *row_inc, s32 *pix_inc)
1654{
1655	u8 ps;
1656	u16 fbw, fbh;
1657
1658	/* FIXME CLUT formats */
1659	switch (color_mode) {
1660	case OMAP_DSS_COLOR_CLUT1:
1661	case OMAP_DSS_COLOR_CLUT2:
1662	case OMAP_DSS_COLOR_CLUT4:
1663	case OMAP_DSS_COLOR_CLUT8:
1664		BUG();
1665		return;
1666	default:
1667		ps = color_mode_to_bpp(color_mode) / 8;
1668		break;
1669	}
1670
1671	DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
1672			width, height);
1673
1674	/* width & height are overlay sizes, convert to fb sizes */
1675
1676	if (rotation == OMAP_DSS_ROT_0 || rotation == OMAP_DSS_ROT_180) {
1677		fbw = width;
1678		fbh = height;
1679	} else {
1680		fbw = height;
1681		fbh = width;
1682	}
1683
1684	/*
1685	 * field 0 = even field = bottom field
1686	 * field 1 = odd field = top field
1687	 */
1688	switch (rotation + mirror * 4) {
1689	case OMAP_DSS_ROT_0:
1690		*offset1 = 0;
1691		if (field_offset)
1692			*offset0 = *offset1 + field_offset * screen_width * ps;
1693		else
1694			*offset0 = *offset1;
1695		*row_inc = pixinc(1 + (screen_width - fbw) +
1696				(fieldmode ? screen_width : 0),
1697				ps);
1698		*pix_inc = pixinc(1, ps);
1699		break;
1700	case OMAP_DSS_ROT_90:
1701		*offset1 = screen_width * (fbh - 1) * ps;
1702		if (field_offset)
1703			*offset0 = *offset1 + field_offset * ps;
1704		else
1705			*offset0 = *offset1;
1706		*row_inc = pixinc(screen_width * (fbh - 1) + 1 +
1707				(fieldmode ? 1 : 0), ps);
1708		*pix_inc = pixinc(-screen_width, ps);
1709		break;
1710	case OMAP_DSS_ROT_180:
1711		*offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
1712		if (field_offset)
1713			*offset0 = *offset1 - field_offset * screen_width * ps;
1714		else
1715			*offset0 = *offset1;
1716		*row_inc = pixinc(-1 -
1717				(screen_width - fbw) -
1718				(fieldmode ? screen_width : 0),
1719				ps);
1720		*pix_inc = pixinc(-1, ps);
1721		break;
1722	case OMAP_DSS_ROT_270:
1723		*offset1 = (fbw - 1) * ps;
1724		if (field_offset)
1725			*offset0 = *offset1 - field_offset * ps;
1726		else
1727			*offset0 = *offset1;
1728		*row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
1729				(fieldmode ? 1 : 0), ps);
1730		*pix_inc = pixinc(screen_width, ps);
1731		break;
1732
1733	/* mirroring */
1734	case OMAP_DSS_ROT_0 + 4:
1735		*offset1 = (fbw - 1) * ps;
1736		if (field_offset)
1737			*offset0 = *offset1 + field_offset * screen_width * ps;
1738		else
1739			*offset0 = *offset1;
1740		*row_inc = pixinc(screen_width * 2 - 1 +
1741				(fieldmode ? screen_width : 0),
1742				ps);
1743		*pix_inc = pixinc(-1, ps);
1744		break;
1745
1746	case OMAP_DSS_ROT_90 + 4:
1747		*offset1 = 0;
1748		if (field_offset)
1749			*offset0 = *offset1 + field_offset * ps;
1750		else
1751			*offset0 = *offset1;
1752		*row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
1753				(fieldmode ? 1 : 0),
1754				ps);
1755		*pix_inc = pixinc(screen_width, ps);
1756		break;
1757
1758	case OMAP_DSS_ROT_180 + 4:
1759		*offset1 = screen_width * (fbh - 1) * ps;
1760		if (field_offset)
1761			*offset0 = *offset1 - field_offset * screen_width * ps;
1762		else
1763			*offset0 = *offset1;
1764		*row_inc = pixinc(1 - screen_width * 2 -
1765				(fieldmode ? screen_width : 0),
1766				ps);
1767		*pix_inc = pixinc(1, ps);
1768		break;
1769
1770	case OMAP_DSS_ROT_270 + 4:
1771		*offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
1772		if (field_offset)
1773			*offset0 = *offset1 - field_offset * ps;
1774		else
1775			*offset0 = *offset1;
1776		*row_inc = pixinc(screen_width * (fbh - 1) - 1 -
1777				(fieldmode ? 1 : 0),
1778				ps);
1779		*pix_inc = pixinc(-screen_width, ps);
1780		break;
1781
1782	default:
1783		BUG();
1784	}
1785}
1786
1787static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
1788		u16 height, u16 out_width, u16 out_height,
1789		enum omap_color_mode color_mode)
1790{
1791	u32 fclk = 0;
1792	/* FIXME venc pclk? */
1793	u64 tmp, pclk = dispc_pclk_rate(channel);
1794
1795	if (height > out_height) {
1796		/* FIXME get real display PPL */
1797		unsigned int ppl = 800;
1798
1799		tmp = pclk * height * out_width;
1800		do_div(tmp, 2 * out_height * ppl);
1801		fclk = tmp;
1802
1803		if (height > 2 * out_height) {
1804			if (ppl == out_width)
1805				return 0;
1806
1807			tmp = pclk * (height - 2 * out_height) * out_width;
1808			do_div(tmp, 2 * out_height * (ppl - out_width));
1809			fclk = max(fclk, (u32) tmp);
1810		}
1811	}
1812
1813	if (width > out_width) {
1814		tmp = pclk * width;
1815		do_div(tmp, out_width);
1816		fclk = max(fclk, (u32) tmp);
1817
1818		if (color_mode == OMAP_DSS_COLOR_RGB24U)
1819			fclk <<= 1;
1820	}
1821
1822	return fclk;
1823}
1824
1825static unsigned long calc_fclk(enum omap_channel channel, u16 width,
1826		u16 height, u16 out_width, u16 out_height)
1827{
1828	unsigned int hf, vf;
1829
1830	/*
1831	 * FIXME how to determine the 'A' factor
1832	 * for the no downscaling case ?
1833	 */
1834
1835	if (width > 3 * out_width)
1836		hf = 4;
1837	else if (width > 2 * out_width)
1838		hf = 3;
1839	else if (width > out_width)
1840		hf = 2;
1841	else
1842		hf = 1;
1843
1844	if (height > out_height)
1845		vf = 2;
1846	else
1847		vf = 1;
1848
1849	/* FIXME venc pclk? */
1850	return dispc_pclk_rate(channel) * vf * hf;
1851}
1852
1853int dispc_setup_plane(enum omap_plane plane,
1854		u32 paddr, u16 screen_width,
1855		u16 pos_x, u16 pos_y,
1856		u16 width, u16 height,
1857		u16 out_width, u16 out_height,
1858		enum omap_color_mode color_mode,
1859		bool ilace,
1860		enum omap_dss_rotation_type rotation_type,
1861		u8 rotation, bool mirror,
1862		u8 global_alpha, u8 pre_mult_alpha,
1863		enum omap_channel channel, u32 puv_addr)
1864{
1865	const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
1866	bool five_taps = 0;
1867	bool fieldmode = 0;
1868	int cconv = 0;
1869	unsigned offset0, offset1;
1870	s32 row_inc;
1871	s32 pix_inc;
1872	u16 frame_height = height;
1873	unsigned int field_offset = 0;
1874
1875	DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
1876	       "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
1877	       plane, paddr, screen_width, pos_x, pos_y,
1878	       width, height,
1879	       out_width, out_height,
1880	       ilace, color_mode,
1881	       rotation, mirror, channel);
1882
1883	if (paddr == 0)
1884		return -EINVAL;
1885
1886	if (ilace && height == out_height)
1887		fieldmode = 1;
1888
1889	if (ilace) {
1890		if (fieldmode)
1891			height /= 2;
1892		pos_y /= 2;
1893		out_height /= 2;
1894
1895		DSSDBG("adjusting for ilace: height %d, pos_y %d, "
1896				"out_height %d\n",
1897				height, pos_y, out_height);
1898	}
1899
1900	if (!dss_feat_color_mode_supported(plane, color_mode))
1901		return -EINVAL;
1902
1903	if (plane == OMAP_DSS_GFX) {
1904		if (width != out_width || height != out_height)
1905			return -EINVAL;
1906	} else {
1907		/* video plane */
1908
1909		unsigned long fclk = 0;
1910
1911		if (out_width < width / maxdownscale ||
1912		   out_width > width * 8)
1913			return -EINVAL;
1914
1915		if (out_height < height / maxdownscale ||
1916		   out_height > height * 8)
1917			return -EINVAL;
1918
1919		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1920			color_mode == OMAP_DSS_COLOR_UYVY ||
1921			color_mode == OMAP_DSS_COLOR_NV12)
1922			cconv = 1;
1923
1924		/* Must use 5-tap filter? */
1925		five_taps = height > out_height * 2;
1926
1927		if (!five_taps) {
1928			fclk = calc_fclk(channel, width, height, out_width,
1929					out_height);
1930
1931			/* Try 5-tap filter if 3-tap fclk is too high */
1932			if (cpu_is_omap34xx() && height > out_height &&
1933					fclk > dispc_fclk_rate())
1934				five_taps = true;
1935		}
1936
1937		if (width > (2048 >> five_taps)) {
1938			DSSERR("failed to set up scaling, fclk too low\n");
1939			return -EINVAL;
1940		}
1941
1942		if (five_taps)
1943			fclk = calc_fclk_five_taps(channel, width, height,
1944					out_width, out_height, color_mode);
1945
1946		DSSDBG("required fclk rate = %lu Hz\n", fclk);
1947		DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
1948
1949		if (!fclk || fclk > dispc_fclk_rate()) {
1950			DSSERR("failed to set up scaling, "
1951					"required fclk rate = %lu Hz, "
1952					"current fclk rate = %lu Hz\n",
1953					fclk, dispc_fclk_rate());
1954			return -EINVAL;
1955		}
1956	}
1957
1958	if (ilace && !fieldmode) {
1959		/*
1960		 * when downscaling the bottom field may have to start several
1961		 * source lines below the top field. Unfortunately ACCUI
1962		 * registers will only hold the fractional part of the offset
1963		 * so the integer part must be added to the base address of the
1964		 * bottom field.
1965		 */
1966		if (!height || height == out_height)
1967			field_offset = 0;
1968		else
1969			field_offset = height / out_height / 2;
1970	}
1971
1972	/* Fields are independent but interleaved in memory. */
1973	if (fieldmode)
1974		field_offset = 1;
1975
1976	if (rotation_type == OMAP_DSS_ROT_DMA)
1977		calc_dma_rotation_offset(rotation, mirror,
1978				screen_width, width, frame_height, color_mode,
1979				fieldmode, field_offset,
1980				&offset0, &offset1, &row_inc, &pix_inc);
1981	else
1982		calc_vrfb_rotation_offset(rotation, mirror,
1983				screen_width, width, frame_height, color_mode,
1984				fieldmode, field_offset,
1985				&offset0, &offset1, &row_inc, &pix_inc);
1986
1987	DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
1988			offset0, offset1, row_inc, pix_inc);
1989
1990	_dispc_set_color_mode(plane, color_mode);
1991
1992	_dispc_set_plane_ba0(plane, paddr + offset0);
1993	_dispc_set_plane_ba1(plane, paddr + offset1);
1994
1995	if (OMAP_DSS_COLOR_NV12 == color_mode) {
1996		_dispc_set_plane_ba0_uv(plane, puv_addr + offset0);
1997		_dispc_set_plane_ba1_uv(plane, puv_addr + offset1);
1998	}
1999
2000
2001	_dispc_set_row_inc(plane, row_inc);
2002	_dispc_set_pix_inc(plane, pix_inc);
2003
2004	DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
2005			out_width, out_height);
2006
2007	_dispc_set_plane_pos(plane, pos_x, pos_y);
2008
2009	_dispc_set_pic_size(plane, width, height);
2010
2011	if (plane != OMAP_DSS_GFX) {
2012		_dispc_set_scaling(plane, width, height,
2013				   out_width, out_height,
2014				   ilace, five_taps, fieldmode,
2015				   color_mode, rotation);
2016		_dispc_set_vid_size(plane, out_width, out_height);
2017		_dispc_set_vid_color_conv(plane, cconv);
2018	}
2019
2020	_dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
2021
2022	_dispc_set_pre_mult_alpha(plane, pre_mult_alpha);
2023	_dispc_setup_global_alpha(plane, global_alpha);
2024
2025	return 0;
2026}
2027
2028int dispc_enable_plane(enum omap_plane plane, bool enable)
2029{
2030	DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
2031
2032	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
2033
2034	return 0;
2035}
2036
2037static void dispc_disable_isr(void *data, u32 mask)
2038{
2039	struct completion *compl = data;
2040	complete(compl);
2041}
2042
2043static void _enable_lcd_out(enum omap_channel channel, bool enable)
2044{
2045	if (channel == OMAP_DSS_CHANNEL_LCD2)
2046		REG_FLD_MO

Large files files are truncated, but you can click here to view the full file