Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2016-2018 Texas Instruments Incorporated - https://www.ti.com/
   4 * Author: Jyri Sarha <jsarha@ti.com>
   5 */
   6
   7#include <linux/clk.h>
   8#include <linux/delay.h>
   9#include <linux/dma-mapping.h>
  10#include <linux/err.h>
  11#include <linux/interrupt.h>
  12#include <linux/io.h>
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/mfd/syscon.h>
  16#include <linux/of.h>
  17#include <linux/of_graph.h>
  18#include <linux/of_device.h>
  19#include <linux/platform_device.h>
  20#include <linux/pm_runtime.h>
  21#include <linux/regmap.h>
  22
  23#include <drm/drm_fourcc.h>
  24#include <drm/drm_fb_cma_helper.h>
  25#include <drm/drm_gem_cma_helper.h>
  26#include <drm/drm_panel.h>
  27
  28#include "tidss_crtc.h"
  29#include "tidss_dispc.h"
  30#include "tidss_drv.h"
  31#include "tidss_irq.h"
  32#include "tidss_plane.h"
  33
  34#include "tidss_dispc_regs.h"
  35#include "tidss_scale_coefs.h"
  36
  37static const u16 tidss_k2g_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
  38	[DSS_REVISION_OFF] =                    0x00,
  39	[DSS_SYSCONFIG_OFF] =                   0x04,
  40	[DSS_SYSSTATUS_OFF] =                   0x08,
  41	[DISPC_IRQ_EOI_OFF] =                   0x20,
  42	[DISPC_IRQSTATUS_RAW_OFF] =             0x24,
  43	[DISPC_IRQSTATUS_OFF] =                 0x28,
  44	[DISPC_IRQENABLE_SET_OFF] =             0x2c,
  45	[DISPC_IRQENABLE_CLR_OFF] =             0x30,
  46
  47	[DISPC_GLOBAL_MFLAG_ATTRIBUTE_OFF] =    0x40,
  48	[DISPC_GLOBAL_BUFFER_OFF] =             0x44,
  49
  50	[DISPC_DBG_CONTROL_OFF] =               0x4c,
  51	[DISPC_DBG_STATUS_OFF] =                0x50,
  52
  53	[DISPC_CLKGATING_DISABLE_OFF] =         0x54,
  54};
  55
  56const struct dispc_features dispc_k2g_feats = {
  57	.min_pclk_khz = 4375,
  58
  59	.max_pclk_khz = {
  60		[DISPC_VP_DPI] = 150000,
  61	},
  62
  63	/*
  64	 * XXX According TRM the RGB input buffer width up to 2560 should
  65	 *     work on 3 taps, but in practice it only works up to 1280.
  66	 */
  67	.scaling = {
  68		.in_width_max_5tap_rgb = 1280,
  69		.in_width_max_3tap_rgb = 1280,
  70		.in_width_max_5tap_yuv = 2560,
  71		.in_width_max_3tap_yuv = 2560,
  72		.upscale_limit = 16,
  73		.downscale_limit_5tap = 4,
  74		.downscale_limit_3tap = 2,
  75		/*
  76		 * The max supported pixel inc value is 255. The value
  77		 * of pixel inc is calculated like this: 1+(xinc-1)*bpp.
  78		 * The maximum bpp of all formats supported by the HW
  79		 * is 8. So the maximum supported xinc value is 32,
  80		 * because 1+(32-1)*8 < 255 < 1+(33-1)*4.
  81		 */
  82		.xinc_max = 32,
  83	},
  84
  85	.subrev = DISPC_K2G,
  86
  87	.common = "common",
  88
  89	.common_regs = tidss_k2g_common_regs,
  90
  91	.num_vps = 1,
  92	.vp_name = { "vp1" },
  93	.ovr_name = { "ovr1" },
  94	.vpclk_name =  { "vp1" },
  95	.vp_bus_type = { DISPC_VP_DPI },
  96
  97	.vp_feat = { .color = {
  98			.has_ctm = true,
  99			.gamma_size = 256,
 100			.gamma_type = TIDSS_GAMMA_8BIT,
 101		},
 102	},
 103
 104	.num_planes = 1,
 105	.vid_name = { "vid1" },
 106	.vid_lite = { false },
 107	.vid_order = { 0 },
 108};
 109
 110static const u16 tidss_am65x_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
 111	[DSS_REVISION_OFF] =			0x4,
 112	[DSS_SYSCONFIG_OFF] =			0x8,
 113	[DSS_SYSSTATUS_OFF] =			0x20,
 114	[DISPC_IRQ_EOI_OFF] =			0x24,
 115	[DISPC_IRQSTATUS_RAW_OFF] =		0x28,
 116	[DISPC_IRQSTATUS_OFF] =			0x2c,
 117	[DISPC_IRQENABLE_SET_OFF] =		0x30,
 118	[DISPC_IRQENABLE_CLR_OFF] =		0x40,
 119	[DISPC_VID_IRQENABLE_OFF] =		0x44,
 120	[DISPC_VID_IRQSTATUS_OFF] =		0x58,
 121	[DISPC_VP_IRQENABLE_OFF] =		0x70,
 122	[DISPC_VP_IRQSTATUS_OFF] =		0x7c,
 123
 124	[WB_IRQENABLE_OFF] =			0x88,
 125	[WB_IRQSTATUS_OFF] =			0x8c,
 126
 127	[DISPC_GLOBAL_MFLAG_ATTRIBUTE_OFF] =	0x90,
 128	[DISPC_GLOBAL_OUTPUT_ENABLE_OFF] =	0x94,
 129	[DISPC_GLOBAL_BUFFER_OFF] =		0x98,
 130	[DSS_CBA_CFG_OFF] =			0x9c,
 131	[DISPC_DBG_CONTROL_OFF] =		0xa0,
 132	[DISPC_DBG_STATUS_OFF] =		0xa4,
 133	[DISPC_CLKGATING_DISABLE_OFF] =		0xa8,
 134	[DISPC_SECURE_DISABLE_OFF] =		0xac,
 135};
 136
 137const struct dispc_features dispc_am65x_feats = {
 138	.max_pclk_khz = {
 139		[DISPC_VP_DPI] = 165000,
 140		[DISPC_VP_OLDI] = 165000,
 141	},
 142
 143	.scaling = {
 144		.in_width_max_5tap_rgb = 1280,
 145		.in_width_max_3tap_rgb = 2560,
 146		.in_width_max_5tap_yuv = 2560,
 147		.in_width_max_3tap_yuv = 4096,
 148		.upscale_limit = 16,
 149		.downscale_limit_5tap = 4,
 150		.downscale_limit_3tap = 2,
 151		/*
 152		 * The max supported pixel inc value is 255. The value
 153		 * of pixel inc is calculated like this: 1+(xinc-1)*bpp.
 154		 * The maximum bpp of all formats supported by the HW
 155		 * is 8. So the maximum supported xinc value is 32,
 156		 * because 1+(32-1)*8 < 255 < 1+(33-1)*4.
 157		 */
 158		.xinc_max = 32,
 159	},
 160
 161	.subrev = DISPC_AM65X,
 162
 163	.common = "common",
 164	.common_regs = tidss_am65x_common_regs,
 165
 166	.num_vps = 2,
 167	.vp_name = { "vp1", "vp2" },
 168	.ovr_name = { "ovr1", "ovr2" },
 169	.vpclk_name =  { "vp1", "vp2" },
 170	.vp_bus_type = { DISPC_VP_OLDI, DISPC_VP_DPI },
 171
 172	.vp_feat = { .color = {
 173			.has_ctm = true,
 174			.gamma_size = 256,
 175			.gamma_type = TIDSS_GAMMA_8BIT,
 176		},
 177	},
 178
 179	.num_planes = 2,
 180	/* note: vid is plane_id 0 and vidl1 is plane_id 1 */
 181	.vid_name = { "vid", "vidl1" },
 182	.vid_lite = { false, true, },
 183	.vid_order = { 1, 0 },
 184};
 185
 186static const u16 tidss_j721e_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
 187	[DSS_REVISION_OFF] =			0x4,
 188	[DSS_SYSCONFIG_OFF] =			0x8,
 189	[DSS_SYSSTATUS_OFF] =			0x20,
 190	[DISPC_IRQ_EOI_OFF] =			0x80,
 191	[DISPC_IRQSTATUS_RAW_OFF] =		0x28,
 192	[DISPC_IRQSTATUS_OFF] =			0x2c,
 193	[DISPC_IRQENABLE_SET_OFF] =		0x30,
 194	[DISPC_IRQENABLE_CLR_OFF] =		0x34,
 195	[DISPC_VID_IRQENABLE_OFF] =		0x38,
 196	[DISPC_VID_IRQSTATUS_OFF] =		0x48,
 197	[DISPC_VP_IRQENABLE_OFF] =		0x58,
 198	[DISPC_VP_IRQSTATUS_OFF] =		0x68,
 199
 200	[WB_IRQENABLE_OFF] =			0x78,
 201	[WB_IRQSTATUS_OFF] =			0x7c,
 202
 203	[DISPC_GLOBAL_MFLAG_ATTRIBUTE_OFF] =	0x98,
 204	[DISPC_GLOBAL_OUTPUT_ENABLE_OFF] =	0x9c,
 205	[DISPC_GLOBAL_BUFFER_OFF] =		0xa0,
 206	[DSS_CBA_CFG_OFF] =			0xa4,
 207	[DISPC_DBG_CONTROL_OFF] =		0xa8,
 208	[DISPC_DBG_STATUS_OFF] =		0xac,
 209	[DISPC_CLKGATING_DISABLE_OFF] =		0xb0,
 210	[DISPC_SECURE_DISABLE_OFF] =		0x90,
 211
 212	[FBDC_REVISION_1_OFF] =			0xb8,
 213	[FBDC_REVISION_2_OFF] =			0xbc,
 214	[FBDC_REVISION_3_OFF] =			0xc0,
 215	[FBDC_REVISION_4_OFF] =			0xc4,
 216	[FBDC_REVISION_5_OFF] =			0xc8,
 217	[FBDC_REVISION_6_OFF] =			0xcc,
 218	[FBDC_COMMON_CONTROL_OFF] =		0xd0,
 219	[FBDC_CONSTANT_COLOR_0_OFF] =		0xd4,
 220	[FBDC_CONSTANT_COLOR_1_OFF] =		0xd8,
 221	[DISPC_CONNECTIONS_OFF] =		0xe4,
 222	[DISPC_MSS_VP1_OFF] =			0xe8,
 223	[DISPC_MSS_VP3_OFF] =			0xec,
 224};
 225
 226const struct dispc_features dispc_j721e_feats = {
 227	.max_pclk_khz = {
 228		[DISPC_VP_DPI] = 170000,
 229		[DISPC_VP_INTERNAL] = 600000,
 230	},
 231
 232	.scaling = {
 233		.in_width_max_5tap_rgb = 2048,
 234		.in_width_max_3tap_rgb = 4096,
 235		.in_width_max_5tap_yuv = 4096,
 236		.in_width_max_3tap_yuv = 4096,
 237		.upscale_limit = 16,
 238		.downscale_limit_5tap = 4,
 239		.downscale_limit_3tap = 2,
 240		/*
 241		 * The max supported pixel inc value is 255. The value
 242		 * of pixel inc is calculated like this: 1+(xinc-1)*bpp.
 243		 * The maximum bpp of all formats supported by the HW
 244		 * is 8. So the maximum supported xinc value is 32,
 245		 * because 1+(32-1)*8 < 255 < 1+(33-1)*4.
 246		 */
 247		.xinc_max = 32,
 248	},
 249
 250	.subrev = DISPC_J721E,
 251
 252	.common = "common_m",
 253	.common_regs = tidss_j721e_common_regs,
 254
 255	.num_vps = 4,
 256	.vp_name = { "vp1", "vp2", "vp3", "vp4" },
 257	.ovr_name = { "ovr1", "ovr2", "ovr3", "ovr4" },
 258	.vpclk_name = { "vp1", "vp2", "vp3", "vp4" },
 259	/* Currently hard coded VP routing (see dispc_initial_config()) */
 260	.vp_bus_type =	{ DISPC_VP_INTERNAL, DISPC_VP_DPI,
 261			  DISPC_VP_INTERNAL, DISPC_VP_DPI, },
 262	.vp_feat = { .color = {
 263			.has_ctm = true,
 264			.gamma_size = 1024,
 265			.gamma_type = TIDSS_GAMMA_10BIT,
 266		},
 267	},
 268	.num_planes = 4,
 269	.vid_name = { "vid1", "vidl1", "vid2", "vidl2" },
 270	.vid_lite = { 0, 1, 0, 1, },
 271	.vid_order = { 1, 3, 0, 2 },
 272};
 273
 274static const u16 *dispc_common_regmap;
 275
 276struct dss_vp_data {
 277	u32 *gamma_table;
 278};
 279
 280struct dispc_device {
 281	struct tidss_device *tidss;
 282	struct device *dev;
 283
 284	void __iomem *base_common;
 285	void __iomem *base_vid[TIDSS_MAX_PLANES];
 286	void __iomem *base_ovr[TIDSS_MAX_PORTS];
 287	void __iomem *base_vp[TIDSS_MAX_PORTS];
 288
 289	struct regmap *oldi_io_ctrl;
 290
 291	struct clk *vp_clk[TIDSS_MAX_PORTS];
 292
 293	const struct dispc_features *feat;
 294
 295	struct clk *fclk;
 296
 297	bool is_enabled;
 298
 299	struct dss_vp_data vp_data[TIDSS_MAX_PORTS];
 300
 301	u32 *fourccs;
 302	u32 num_fourccs;
 303
 304	u32 memory_bandwidth_limit;
 305};
 306
 307static void dispc_write(struct dispc_device *dispc, u16 reg, u32 val)
 308{
 309	iowrite32(val, dispc->base_common + reg);
 310}
 311
 312static u32 dispc_read(struct dispc_device *dispc, u16 reg)
 313{
 314	return ioread32(dispc->base_common + reg);
 315}
 316
 317static
 318void dispc_vid_write(struct dispc_device *dispc, u32 hw_plane, u16 reg, u32 val)
 319{
 320	void __iomem *base = dispc->base_vid[hw_plane];
 321
 322	iowrite32(val, base + reg);
 323}
 324
 325static u32 dispc_vid_read(struct dispc_device *dispc, u32 hw_plane, u16 reg)
 326{
 327	void __iomem *base = dispc->base_vid[hw_plane];
 328
 329	return ioread32(base + reg);
 330}
 331
 332static void dispc_ovr_write(struct dispc_device *dispc, u32 hw_videoport,
 333			    u16 reg, u32 val)
 334{
 335	void __iomem *base = dispc->base_ovr[hw_videoport];
 336
 337	iowrite32(val, base + reg);
 338}
 339
 340static u32 dispc_ovr_read(struct dispc_device *dispc, u32 hw_videoport, u16 reg)
 341{
 342	void __iomem *base = dispc->base_ovr[hw_videoport];
 343
 344	return ioread32(base + reg);
 345}
 346
 347static void dispc_vp_write(struct dispc_device *dispc, u32 hw_videoport,
 348			   u16 reg, u32 val)
 349{
 350	void __iomem *base = dispc->base_vp[hw_videoport];
 351
 352	iowrite32(val, base + reg);
 353}
 354
 355static u32 dispc_vp_read(struct dispc_device *dispc, u32 hw_videoport, u16 reg)
 356{
 357	void __iomem *base = dispc->base_vp[hw_videoport];
 358
 359	return ioread32(base + reg);
 360}
 361
 362/*
 363 * TRM gives bitfields as start:end, where start is the higher bit
 364 * number. For example 7:0
 365 */
 366
 367static u32 FLD_MASK(u32 start, u32 end)
 368{
 369	return ((1 << (start - end + 1)) - 1) << end;
 370}
 371
 372static u32 FLD_VAL(u32 val, u32 start, u32 end)
 373{
 374	return (val << end) & FLD_MASK(start, end);
 375}
 376
 377static u32 FLD_GET(u32 val, u32 start, u32 end)
 378{
 379	return (val & FLD_MASK(start, end)) >> end;
 380}
 381
 382static u32 FLD_MOD(u32 orig, u32 val, u32 start, u32 end)
 383{
 384	return (orig & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end);
 385}
 386
 387static u32 REG_GET(struct dispc_device *dispc, u32 idx, u32 start, u32 end)
 388{
 389	return FLD_GET(dispc_read(dispc, idx), start, end);
 390}
 391
 392static void REG_FLD_MOD(struct dispc_device *dispc, u32 idx, u32 val,
 393			u32 start, u32 end)
 394{
 395	dispc_write(dispc, idx, FLD_MOD(dispc_read(dispc, idx), val,
 396					start, end));
 397}
 398
 399static u32 VID_REG_GET(struct dispc_device *dispc, u32 hw_plane, u32 idx,
 400		       u32 start, u32 end)
 401{
 402	return FLD_GET(dispc_vid_read(dispc, hw_plane, idx), start, end);
 403}
 404
 405static void VID_REG_FLD_MOD(struct dispc_device *dispc, u32 hw_plane, u32 idx,
 406			    u32 val, u32 start, u32 end)
 407{
 408	dispc_vid_write(dispc, hw_plane, idx,
 409			FLD_MOD(dispc_vid_read(dispc, hw_plane, idx),
 410				val, start, end));
 411}
 412
 413static u32 VP_REG_GET(struct dispc_device *dispc, u32 vp, u32 idx,
 414		      u32 start, u32 end)
 415{
 416	return FLD_GET(dispc_vp_read(dispc, vp, idx), start, end);
 417}
 418
 419static void VP_REG_FLD_MOD(struct dispc_device *dispc, u32 vp, u32 idx, u32 val,
 420			   u32 start, u32 end)
 421{
 422	dispc_vp_write(dispc, vp, idx, FLD_MOD(dispc_vp_read(dispc, vp, idx),
 423					       val, start, end));
 424}
 425
 426__maybe_unused
 427static u32 OVR_REG_GET(struct dispc_device *dispc, u32 ovr, u32 idx,
 428		       u32 start, u32 end)
 429{
 430	return FLD_GET(dispc_ovr_read(dispc, ovr, idx), start, end);
 431}
 432
 433static void OVR_REG_FLD_MOD(struct dispc_device *dispc, u32 ovr, u32 idx,
 434			    u32 val, u32 start, u32 end)
 435{
 436	dispc_ovr_write(dispc, ovr, idx,
 437			FLD_MOD(dispc_ovr_read(dispc, ovr, idx),
 438				val, start, end));
 439}
 440
 441static dispc_irq_t dispc_vp_irq_from_raw(u32 stat, u32 hw_videoport)
 442{
 443	dispc_irq_t vp_stat = 0;
 444
 445	if (stat & BIT(0))
 446		vp_stat |= DSS_IRQ_VP_FRAME_DONE(hw_videoport);
 447	if (stat & BIT(1))
 448		vp_stat |= DSS_IRQ_VP_VSYNC_EVEN(hw_videoport);
 449	if (stat & BIT(2))
 450		vp_stat |= DSS_IRQ_VP_VSYNC_ODD(hw_videoport);
 451	if (stat & BIT(4))
 452		vp_stat |= DSS_IRQ_VP_SYNC_LOST(hw_videoport);
 453
 454	return vp_stat;
 455}
 456
 457static u32 dispc_vp_irq_to_raw(dispc_irq_t vpstat, u32 hw_videoport)
 458{
 459	u32 stat = 0;
 460
 461	if (vpstat & DSS_IRQ_VP_FRAME_DONE(hw_videoport))
 462		stat |= BIT(0);
 463	if (vpstat & DSS_IRQ_VP_VSYNC_EVEN(hw_videoport))
 464		stat |= BIT(1);
 465	if (vpstat & DSS_IRQ_VP_VSYNC_ODD(hw_videoport))
 466		stat |= BIT(2);
 467	if (vpstat & DSS_IRQ_VP_SYNC_LOST(hw_videoport))
 468		stat |= BIT(4);
 469
 470	return stat;
 471}
 472
 473static dispc_irq_t dispc_vid_irq_from_raw(u32 stat, u32 hw_plane)
 474{
 475	dispc_irq_t vid_stat = 0;
 476
 477	if (stat & BIT(0))
 478		vid_stat |= DSS_IRQ_PLANE_FIFO_UNDERFLOW(hw_plane);
 479
 480	return vid_stat;
 481}
 482
 483static u32 dispc_vid_irq_to_raw(dispc_irq_t vidstat, u32 hw_plane)
 484{
 485	u32 stat = 0;
 486
 487	if (vidstat & DSS_IRQ_PLANE_FIFO_UNDERFLOW(hw_plane))
 488		stat |= BIT(0);
 489
 490	return stat;
 491}
 492
 493static dispc_irq_t dispc_k2g_vp_read_irqstatus(struct dispc_device *dispc,
 494					       u32 hw_videoport)
 495{
 496	u32 stat = dispc_vp_read(dispc, hw_videoport, DISPC_VP_K2G_IRQSTATUS);
 497
 498	return dispc_vp_irq_from_raw(stat, hw_videoport);
 499}
 500
 501static void dispc_k2g_vp_write_irqstatus(struct dispc_device *dispc,
 502					 u32 hw_videoport, dispc_irq_t vpstat)
 503{
 504	u32 stat = dispc_vp_irq_to_raw(vpstat, hw_videoport);
 505
 506	dispc_vp_write(dispc, hw_videoport, DISPC_VP_K2G_IRQSTATUS, stat);
 507}
 508
 509static dispc_irq_t dispc_k2g_vid_read_irqstatus(struct dispc_device *dispc,
 510						u32 hw_plane)
 511{
 512	u32 stat = dispc_vid_read(dispc, hw_plane, DISPC_VID_K2G_IRQSTATUS);
 513
 514	return dispc_vid_irq_from_raw(stat, hw_plane);
 515}
 516
 517static void dispc_k2g_vid_write_irqstatus(struct dispc_device *dispc,
 518					  u32 hw_plane, dispc_irq_t vidstat)
 519{
 520	u32 stat = dispc_vid_irq_to_raw(vidstat, hw_plane);
 521
 522	dispc_vid_write(dispc, hw_plane, DISPC_VID_K2G_IRQSTATUS, stat);
 523}
 524
 525static dispc_irq_t dispc_k2g_vp_read_irqenable(struct dispc_device *dispc,
 526					       u32 hw_videoport)
 527{
 528	u32 stat = dispc_vp_read(dispc, hw_videoport, DISPC_VP_K2G_IRQENABLE);
 529
 530	return dispc_vp_irq_from_raw(stat, hw_videoport);
 531}
 532
 533static void dispc_k2g_vp_set_irqenable(struct dispc_device *dispc,
 534				       u32 hw_videoport, dispc_irq_t vpstat)
 535{
 536	u32 stat = dispc_vp_irq_to_raw(vpstat, hw_videoport);
 537
 538	dispc_vp_write(dispc, hw_videoport, DISPC_VP_K2G_IRQENABLE, stat);
 539}
 540
 541static dispc_irq_t dispc_k2g_vid_read_irqenable(struct dispc_device *dispc,
 542						u32 hw_plane)
 543{
 544	u32 stat = dispc_vid_read(dispc, hw_plane, DISPC_VID_K2G_IRQENABLE);
 545
 546	return dispc_vid_irq_from_raw(stat, hw_plane);
 547}
 548
 549static void dispc_k2g_vid_set_irqenable(struct dispc_device *dispc,
 550					u32 hw_plane, dispc_irq_t vidstat)
 551{
 552	u32 stat = dispc_vid_irq_to_raw(vidstat, hw_plane);
 553
 554	dispc_vid_write(dispc, hw_plane, DISPC_VID_K2G_IRQENABLE, stat);
 555}
 556
 557static void dispc_k2g_clear_irqstatus(struct dispc_device *dispc,
 558				      dispc_irq_t mask)
 559{
 560	dispc_k2g_vp_write_irqstatus(dispc, 0, mask);
 561	dispc_k2g_vid_write_irqstatus(dispc, 0, mask);
 562}
 563
 564static
 565dispc_irq_t dispc_k2g_read_and_clear_irqstatus(struct dispc_device *dispc)
 566{
 567	dispc_irq_t stat = 0;
 568
 569	/* always clear the top level irqstatus */
 570	dispc_write(dispc, DISPC_IRQSTATUS,
 571		    dispc_read(dispc, DISPC_IRQSTATUS));
 572
 573	stat |= dispc_k2g_vp_read_irqstatus(dispc, 0);
 574	stat |= dispc_k2g_vid_read_irqstatus(dispc, 0);
 575
 576	dispc_k2g_clear_irqstatus(dispc, stat);
 577
 578	return stat;
 579}
 580
 581static dispc_irq_t dispc_k2g_read_irqenable(struct dispc_device *dispc)
 582{
 583	dispc_irq_t stat = 0;
 584
 585	stat |= dispc_k2g_vp_read_irqenable(dispc, 0);
 586	stat |= dispc_k2g_vid_read_irqenable(dispc, 0);
 587
 588	return stat;
 589}
 590
 591static
 592void dispc_k2g_set_irqenable(struct dispc_device *dispc, dispc_irq_t mask)
 593{
 594	dispc_irq_t old_mask = dispc_k2g_read_irqenable(dispc);
 595
 596	/* clear the irqstatus for newly enabled irqs */
 597	dispc_k2g_clear_irqstatus(dispc, (mask ^ old_mask) & mask);
 598
 599	dispc_k2g_vp_set_irqenable(dispc, 0, mask);
 600	dispc_k2g_vid_set_irqenable(dispc, 0, mask);
 601
 602	dispc_write(dispc, DISPC_IRQENABLE_SET, (1 << 0) | (1 << 7));
 603
 604	/* flush posted write */
 605	dispc_k2g_read_irqenable(dispc);
 606}
 607
 608static dispc_irq_t dispc_k3_vp_read_irqstatus(struct dispc_device *dispc,
 609					      u32 hw_videoport)
 610{
 611	u32 stat = dispc_read(dispc, DISPC_VP_IRQSTATUS(hw_videoport));
 612
 613	return dispc_vp_irq_from_raw(stat, hw_videoport);
 614}
 615
 616static void dispc_k3_vp_write_irqstatus(struct dispc_device *dispc,
 617					u32 hw_videoport, dispc_irq_t vpstat)
 618{
 619	u32 stat = dispc_vp_irq_to_raw(vpstat, hw_videoport);
 620
 621	dispc_write(dispc, DISPC_VP_IRQSTATUS(hw_videoport), stat);
 622}
 623
 624static dispc_irq_t dispc_k3_vid_read_irqstatus(struct dispc_device *dispc,
 625					       u32 hw_plane)
 626{
 627	u32 stat = dispc_read(dispc, DISPC_VID_IRQSTATUS(hw_plane));
 628
 629	return dispc_vid_irq_from_raw(stat, hw_plane);
 630}
 631
 632static void dispc_k3_vid_write_irqstatus(struct dispc_device *dispc,
 633					 u32 hw_plane, dispc_irq_t vidstat)
 634{
 635	u32 stat = dispc_vid_irq_to_raw(vidstat, hw_plane);
 636
 637	dispc_write(dispc, DISPC_VID_IRQSTATUS(hw_plane), stat);
 638}
 639
 640static dispc_irq_t dispc_k3_vp_read_irqenable(struct dispc_device *dispc,
 641					      u32 hw_videoport)
 642{
 643	u32 stat = dispc_read(dispc, DISPC_VP_IRQENABLE(hw_videoport));
 644
 645	return dispc_vp_irq_from_raw(stat, hw_videoport);
 646}
 647
 648static void dispc_k3_vp_set_irqenable(struct dispc_device *dispc,
 649				      u32 hw_videoport, dispc_irq_t vpstat)
 650{
 651	u32 stat = dispc_vp_irq_to_raw(vpstat, hw_videoport);
 652
 653	dispc_write(dispc, DISPC_VP_IRQENABLE(hw_videoport), stat);
 654}
 655
 656static dispc_irq_t dispc_k3_vid_read_irqenable(struct dispc_device *dispc,
 657					       u32 hw_plane)
 658{
 659	u32 stat = dispc_read(dispc, DISPC_VID_IRQENABLE(hw_plane));
 660
 661	return dispc_vid_irq_from_raw(stat, hw_plane);
 662}
 663
 664static void dispc_k3_vid_set_irqenable(struct dispc_device *dispc,
 665				       u32 hw_plane, dispc_irq_t vidstat)
 666{
 667	u32 stat = dispc_vid_irq_to_raw(vidstat, hw_plane);
 668
 669	dispc_write(dispc, DISPC_VID_IRQENABLE(hw_plane), stat);
 670}
 671
 672static
 673void dispc_k3_clear_irqstatus(struct dispc_device *dispc, dispc_irq_t clearmask)
 674{
 675	unsigned int i;
 676	u32 top_clear = 0;
 677
 678	for (i = 0; i < dispc->feat->num_vps; ++i) {
 679		if (clearmask & DSS_IRQ_VP_MASK(i)) {
 680			dispc_k3_vp_write_irqstatus(dispc, i, clearmask);
 681			top_clear |= BIT(i);
 682		}
 683	}
 684	for (i = 0; i < dispc->feat->num_planes; ++i) {
 685		if (clearmask & DSS_IRQ_PLANE_MASK(i)) {
 686			dispc_k3_vid_write_irqstatus(dispc, i, clearmask);
 687			top_clear |= BIT(4 + i);
 688		}
 689	}
 690	if (dispc->feat->subrev == DISPC_K2G)
 691		return;
 692
 693	dispc_write(dispc, DISPC_IRQSTATUS, top_clear);
 694
 695	/* Flush posted writes */
 696	dispc_read(dispc, DISPC_IRQSTATUS);
 697}
 698
 699static
 700dispc_irq_t dispc_k3_read_and_clear_irqstatus(struct dispc_device *dispc)
 701{
 702	dispc_irq_t status = 0;
 703	unsigned int i;
 704
 705	for (i = 0; i < dispc->feat->num_vps; ++i)
 706		status |= dispc_k3_vp_read_irqstatus(dispc, i);
 707
 708	for (i = 0; i < dispc->feat->num_planes; ++i)
 709		status |= dispc_k3_vid_read_irqstatus(dispc, i);
 710
 711	dispc_k3_clear_irqstatus(dispc, status);
 712
 713	return status;
 714}
 715
 716static dispc_irq_t dispc_k3_read_irqenable(struct dispc_device *dispc)
 717{
 718	dispc_irq_t enable = 0;
 719	unsigned int i;
 720
 721	for (i = 0; i < dispc->feat->num_vps; ++i)
 722		enable |= dispc_k3_vp_read_irqenable(dispc, i);
 723
 724	for (i = 0; i < dispc->feat->num_planes; ++i)
 725		enable |= dispc_k3_vid_read_irqenable(dispc, i);
 726
 727	return enable;
 728}
 729
 730static void dispc_k3_set_irqenable(struct dispc_device *dispc,
 731				   dispc_irq_t mask)
 732{
 733	unsigned int i;
 734	u32 main_enable = 0, main_disable = 0;
 735	dispc_irq_t old_mask;
 736
 737	old_mask = dispc_k3_read_irqenable(dispc);
 738
 739	/* clear the irqstatus for newly enabled irqs */
 740	dispc_k3_clear_irqstatus(dispc, (old_mask ^ mask) & mask);
 741
 742	for (i = 0; i < dispc->feat->num_vps; ++i) {
 743		dispc_k3_vp_set_irqenable(dispc, i, mask);
 744		if (mask & DSS_IRQ_VP_MASK(i))
 745			main_enable |= BIT(i);		/* VP IRQ */
 746		else
 747			main_disable |= BIT(i);		/* VP IRQ */
 748	}
 749
 750	for (i = 0; i < dispc->feat->num_planes; ++i) {
 751		dispc_k3_vid_set_irqenable(dispc, i, mask);
 752		if (mask & DSS_IRQ_PLANE_MASK(i))
 753			main_enable |= BIT(i + 4);	/* VID IRQ */
 754		else
 755			main_disable |= BIT(i + 4);	/* VID IRQ */
 756	}
 757
 758	if (main_enable)
 759		dispc_write(dispc, DISPC_IRQENABLE_SET, main_enable);
 760
 761	if (main_disable)
 762		dispc_write(dispc, DISPC_IRQENABLE_CLR, main_disable);
 763
 764	/* Flush posted writes */
 765	dispc_read(dispc, DISPC_IRQENABLE_SET);
 766}
 767
 768dispc_irq_t dispc_read_and_clear_irqstatus(struct dispc_device *dispc)
 769{
 770	switch (dispc->feat->subrev) {
 771	case DISPC_K2G:
 772		return dispc_k2g_read_and_clear_irqstatus(dispc);
 773	case DISPC_AM65X:
 774	case DISPC_J721E:
 775		return dispc_k3_read_and_clear_irqstatus(dispc);
 776	default:
 777		WARN_ON(1);
 778		return 0;
 779	}
 780}
 781
 782void dispc_set_irqenable(struct dispc_device *dispc, dispc_irq_t mask)
 783{
 784	switch (dispc->feat->subrev) {
 785	case DISPC_K2G:
 786		dispc_k2g_set_irqenable(dispc, mask);
 787		break;
 788	case DISPC_AM65X:
 789	case DISPC_J721E:
 790		dispc_k3_set_irqenable(dispc, mask);
 791		break;
 792	default:
 793		WARN_ON(1);
 794		break;
 795	}
 796}
 797
 798enum dispc_oldi_mode_reg_val { SPWG_18 = 0, JEIDA_24 = 1, SPWG_24 = 2 };
 799
 800struct dispc_bus_format {
 801	u32 bus_fmt;
 802	u32 data_width;
 803	bool is_oldi_fmt;
 804	enum dispc_oldi_mode_reg_val oldi_mode_reg_val;
 805};
 806
 807static const struct dispc_bus_format dispc_bus_formats[] = {
 808	{ MEDIA_BUS_FMT_RGB444_1X12,		12, false, 0 },
 809	{ MEDIA_BUS_FMT_RGB565_1X16,		16, false, 0 },
 810	{ MEDIA_BUS_FMT_RGB666_1X18,		18, false, 0 },
 811	{ MEDIA_BUS_FMT_RGB888_1X24,		24, false, 0 },
 812	{ MEDIA_BUS_FMT_RGB101010_1X30,		30, false, 0 },
 813	{ MEDIA_BUS_FMT_RGB121212_1X36,		36, false, 0 },
 814	{ MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,	18, true, SPWG_18 },
 815	{ MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,	24, true, SPWG_24 },
 816	{ MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,	24, true, JEIDA_24 },
 817};
 818
 819static const
 820struct dispc_bus_format *dispc_vp_find_bus_fmt(struct dispc_device *dispc,
 821					       u32 hw_videoport,
 822					       u32 bus_fmt, u32 bus_flags)
 823{
 824	unsigned int i;
 825
 826	for (i = 0; i < ARRAY_SIZE(dispc_bus_formats); ++i) {
 827		if (dispc_bus_formats[i].bus_fmt == bus_fmt)
 828			return &dispc_bus_formats[i];
 829	}
 830
 831	return NULL;
 832}
 833
 834int dispc_vp_bus_check(struct dispc_device *dispc, u32 hw_videoport,
 835		       const struct drm_crtc_state *state)
 836{
 837	const struct tidss_crtc_state *tstate = to_tidss_crtc_state(state);
 838	const struct dispc_bus_format *fmt;
 839
 840	fmt = dispc_vp_find_bus_fmt(dispc, hw_videoport, tstate->bus_format,
 841				    tstate->bus_flags);
 842	if (!fmt) {
 843		dev_dbg(dispc->dev, "%s: Unsupported bus format: %u\n",
 844			__func__, tstate->bus_format);
 845		return -EINVAL;
 846	}
 847
 848	if (dispc->feat->vp_bus_type[hw_videoport] != DISPC_VP_OLDI &&
 849	    fmt->is_oldi_fmt) {
 850		dev_dbg(dispc->dev, "%s: %s is not OLDI-port\n",
 851			__func__, dispc->feat->vp_name[hw_videoport]);
 852		return -EINVAL;
 853	}
 854
 855	return 0;
 856}
 857
 858static void dispc_oldi_tx_power(struct dispc_device *dispc, bool power)
 859{
 860	u32 val = power ? 0 : OLDI_PWRDN_TX;
 861
 862	if (WARN_ON(!dispc->oldi_io_ctrl))
 863		return;
 864
 865	regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT0_IO_CTRL,
 866			   OLDI_PWRDN_TX, val);
 867	regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT1_IO_CTRL,
 868			   OLDI_PWRDN_TX, val);
 869	regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT2_IO_CTRL,
 870			   OLDI_PWRDN_TX, val);
 871	regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT3_IO_CTRL,
 872			   OLDI_PWRDN_TX, val);
 873	regmap_update_bits(dispc->oldi_io_ctrl, OLDI_CLK_IO_CTRL,
 874			   OLDI_PWRDN_TX, val);
 875}
 876
 877static void dispc_set_num_datalines(struct dispc_device *dispc,
 878				    u32 hw_videoport, int num_lines)
 879{
 880	int v;
 881
 882	switch (num_lines) {
 883	case 12:
 884		v = 0; break;
 885	case 16:
 886		v = 1; break;
 887	case 18:
 888		v = 2; break;
 889	case 24:
 890		v = 3; break;
 891	case 30:
 892		v = 4; break;
 893	case 36:
 894		v = 5; break;
 895	default:
 896		WARN_ON(1);
 897		v = 3;
 898	}
 899
 900	VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, v, 10, 8);
 901}
 902
 903static void dispc_enable_oldi(struct dispc_device *dispc, u32 hw_videoport,
 904			      const struct dispc_bus_format *fmt)
 905{
 906	u32 oldi_cfg = 0;
 907	u32 oldi_reset_bit = BIT(5 + hw_videoport);
 908	int count = 0;
 909
 910	/*
 911	 * For the moment DUALMODESYNC, MASTERSLAVE, MODE, and SRC
 912	 * bits of DISPC_VP_DSS_OLDI_CFG are set statically to 0.
 913	 */
 914
 915	if (fmt->data_width == 24)
 916		oldi_cfg |= BIT(8); /* MSB */
 917	else if (fmt->data_width != 18)
 918		dev_warn(dispc->dev, "%s: %d port width not supported\n",
 919			 __func__, fmt->data_width);
 920
 921	oldi_cfg |= BIT(7); /* DEPOL */
 922
 923	oldi_cfg = FLD_MOD(oldi_cfg, fmt->oldi_mode_reg_val, 3, 1);
 924
 925	oldi_cfg |= BIT(12); /* SOFTRST */
 926
 927	oldi_cfg |= BIT(0); /* ENABLE */
 928
 929	dispc_vp_write(dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, oldi_cfg);
 930
 931	while (!(oldi_reset_bit & dispc_read(dispc, DSS_SYSSTATUS)) &&
 932	       count < 10000)
 933		count++;
 934
 935	if (!(oldi_reset_bit & dispc_read(dispc, DSS_SYSSTATUS)))
 936		dev_warn(dispc->dev, "%s: timeout waiting OLDI reset done\n",
 937			 __func__);
 938}
 939
 940void dispc_vp_prepare(struct dispc_device *dispc, u32 hw_videoport,
 941		      const struct drm_crtc_state *state)
 942{
 943	const struct tidss_crtc_state *tstate = to_tidss_crtc_state(state);
 944	const struct dispc_bus_format *fmt;
 945
 946	fmt = dispc_vp_find_bus_fmt(dispc, hw_videoport, tstate->bus_format,
 947				    tstate->bus_flags);
 948
 949	if (WARN_ON(!fmt))
 950		return;
 951
 952	if (dispc->feat->vp_bus_type[hw_videoport] == DISPC_VP_OLDI) {
 953		dispc_oldi_tx_power(dispc, true);
 954
 955		dispc_enable_oldi(dispc, hw_videoport, fmt);
 956	}
 957}
 958
 959void dispc_vp_enable(struct dispc_device *dispc, u32 hw_videoport,
 960		     const struct drm_crtc_state *state)
 961{
 962	const struct drm_display_mode *mode = &state->adjusted_mode;
 963	const struct tidss_crtc_state *tstate = to_tidss_crtc_state(state);
 964	bool align, onoff, rf, ieo, ipc, ihs, ivs;
 965	const struct dispc_bus_format *fmt;
 966	u32 hsw, hfp, hbp, vsw, vfp, vbp;
 967
 968	fmt = dispc_vp_find_bus_fmt(dispc, hw_videoport, tstate->bus_format,
 969				    tstate->bus_flags);
 970
 971	if (WARN_ON(!fmt))
 972		return;
 973
 974	dispc_set_num_datalines(dispc, hw_videoport, fmt->data_width);
 975
 976	hfp = mode->hsync_start - mode->hdisplay;
 977	hsw = mode->hsync_end - mode->hsync_start;
 978	hbp = mode->htotal - mode->hsync_end;
 979
 980	vfp = mode->vsync_start - mode->vdisplay;
 981	vsw = mode->vsync_end - mode->vsync_start;
 982	vbp = mode->vtotal - mode->vsync_end;
 983
 984	dispc_vp_write(dispc, hw_videoport, DISPC_VP_TIMING_H,
 985		       FLD_VAL(hsw - 1, 7, 0) |
 986		       FLD_VAL(hfp - 1, 19, 8) |
 987		       FLD_VAL(hbp - 1, 31, 20));
 988
 989	dispc_vp_write(dispc, hw_videoport, DISPC_VP_TIMING_V,
 990		       FLD_VAL(vsw - 1, 7, 0) |
 991		       FLD_VAL(vfp, 19, 8) |
 992		       FLD_VAL(vbp, 31, 20));
 993
 994	ivs = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
 995
 996	ihs = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
 997
 998	ieo = !!(tstate->bus_flags & DRM_BUS_FLAG_DE_LOW);
 999
1000	ipc = !!(tstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE);
1001
1002	/* always use the 'rf' setting */
1003	onoff = true;
1004
1005	rf = !!(tstate->bus_flags & DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE);
1006
1007	/* always use aligned syncs */
1008	align = true;
1009
1010	/* always use DE_HIGH for OLDI */
1011	if (dispc->feat->vp_bus_type[hw_videoport] == DISPC_VP_OLDI)
1012		ieo = false;
1013
1014	dispc_vp_write(dispc, hw_videoport, DISPC_VP_POL_FREQ,
1015		       FLD_VAL(align, 18, 18) |
1016		       FLD_VAL(onoff, 17, 17) |
1017		       FLD_VAL(rf, 16, 16) |
1018		       FLD_VAL(ieo, 15, 15) |
1019		       FLD_VAL(ipc, 14, 14) |
1020		       FLD_VAL(ihs, 13, 13) |
1021		       FLD_VAL(ivs, 12, 12));
1022
1023	dispc_vp_write(dispc, hw_videoport, DISPC_VP_SIZE_SCREEN,
1024		       FLD_VAL(mode->hdisplay - 1, 11, 0) |
1025		       FLD_VAL(mode->vdisplay - 1, 27, 16));
1026
1027	VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 1, 0, 0);
1028}
1029
1030void dispc_vp_disable(struct dispc_device *dispc, u32 hw_videoport)
1031{
1032	VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 0, 0, 0);
1033}
1034
1035void dispc_vp_unprepare(struct dispc_device *dispc, u32 hw_videoport)
1036{
1037	if (dispc->feat->vp_bus_type[hw_videoport] == DISPC_VP_OLDI) {
1038		dispc_vp_write(dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, 0);
1039
1040		dispc_oldi_tx_power(dispc, false);
1041	}
1042}
1043
1044bool dispc_vp_go_busy(struct dispc_device *dispc, u32 hw_videoport)
1045{
1046	return VP_REG_GET(dispc, hw_videoport, DISPC_VP_CONTROL, 5, 5);
1047}
1048
1049void dispc_vp_go(struct dispc_device *dispc, u32 hw_videoport)
1050{
1051	WARN_ON(VP_REG_GET(dispc, hw_videoport, DISPC_VP_CONTROL, 5, 5));
1052	VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 1, 5, 5);
1053}
1054
1055enum c8_to_c12_mode { C8_TO_C12_REPLICATE, C8_TO_C12_MAX, C8_TO_C12_MIN };
1056
1057static u16 c8_to_c12(u8 c8, enum c8_to_c12_mode mode)
1058{
1059	u16 c12;
1060
1061	c12 = c8 << 4;
1062
1063	switch (mode) {
1064	case C8_TO_C12_REPLICATE:
1065		/* Copy c8 4 MSB to 4 LSB for full scale c12 */
1066		c12 |= c8 >> 4;
1067		break;
1068	case C8_TO_C12_MAX:
1069		c12 |= 0xF;
1070		break;
1071	default:
1072	case C8_TO_C12_MIN:
1073		break;
1074	}
1075
1076	return c12;
1077}
1078
1079static u64 argb8888_to_argb12121212(u32 argb8888, enum c8_to_c12_mode m)
1080{
1081	u8 a, r, g, b;
1082	u64 v;
1083
1084	a = (argb8888 >> 24) & 0xff;
1085	r = (argb8888 >> 16) & 0xff;
1086	g = (argb8888 >> 8) & 0xff;
1087	b = (argb8888 >> 0) & 0xff;
1088
1089	v = ((u64)c8_to_c12(a, m) << 36) | ((u64)c8_to_c12(r, m) << 24) |
1090		((u64)c8_to_c12(g, m) << 12) | (u64)c8_to_c12(b, m);
1091
1092	return v;
1093}
1094
1095static void dispc_vp_set_default_color(struct dispc_device *dispc,
1096				       u32 hw_videoport, u32 default_color)
1097{
1098	u64 v;
1099
1100	v = argb8888_to_argb12121212(default_color, C8_TO_C12_REPLICATE);
1101
1102	dispc_ovr_write(dispc, hw_videoport,
1103			DISPC_OVR_DEFAULT_COLOR, v & 0xffffffff);
1104	dispc_ovr_write(dispc, hw_videoport,
1105			DISPC_OVR_DEFAULT_COLOR2, (v >> 32) & 0xffff);
1106}
1107
1108enum drm_mode_status dispc_vp_mode_valid(struct dispc_device *dispc,
1109					 u32 hw_videoport,
1110					 const struct drm_display_mode *mode)
1111{
1112	u32 hsw, hfp, hbp, vsw, vfp, vbp;
1113	enum dispc_vp_bus_type bus_type;
1114	int max_pclk;
1115
1116	bus_type = dispc->feat->vp_bus_type[hw_videoport];
1117
1118	max_pclk = dispc->feat->max_pclk_khz[bus_type];
1119
1120	if (WARN_ON(max_pclk == 0))
1121		return MODE_BAD;
1122
1123	if (mode->clock < dispc->feat->min_pclk_khz)
1124		return MODE_CLOCK_LOW;
1125
1126	if (mode->clock > max_pclk)
1127		return MODE_CLOCK_HIGH;
1128
1129	if (mode->hdisplay > 4096)
1130		return MODE_BAD;
1131
1132	if (mode->vdisplay > 4096)
1133		return MODE_BAD;
1134
1135	/* TODO: add interlace support */
1136	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1137		return MODE_NO_INTERLACE;
1138
1139	/*
1140	 * Enforce the output width is divisible by 2. Actually this
1141	 * is only needed in following cases:
1142	 * - YUV output selected (BT656, BT1120)
1143	 * - Dithering enabled
1144	 * - TDM with TDMCycleFormat == 3
1145	 * But for simplicity we enforce that always.
1146	 */
1147	if ((mode->hdisplay % 2) != 0)
1148		return MODE_BAD_HVALUE;
1149
1150	hfp = mode->hsync_start - mode->hdisplay;
1151	hsw = mode->hsync_end - mode->hsync_start;
1152	hbp = mode->htotal - mode->hsync_end;
1153
1154	vfp = mode->vsync_start - mode->vdisplay;
1155	vsw = mode->vsync_end - mode->vsync_start;
1156	vbp = mode->vtotal - mode->vsync_end;
1157
1158	if (hsw < 1 || hsw > 256 ||
1159	    hfp < 1 || hfp > 4096 ||
1160	    hbp < 1 || hbp > 4096)
1161		return MODE_BAD_HVALUE;
1162
1163	if (vsw < 1 || vsw > 256 ||
1164	    vfp > 4095 || vbp > 4095)
1165		return MODE_BAD_VVALUE;
1166
1167	if (dispc->memory_bandwidth_limit) {
1168		const unsigned int bpp = 4;
1169		u64 bandwidth;
1170
1171		bandwidth = 1000 * mode->clock;
1172		bandwidth = bandwidth * mode->hdisplay * mode->vdisplay * bpp;
1173		bandwidth = div_u64(bandwidth, mode->htotal * mode->vtotal);
1174
1175		if (dispc->memory_bandwidth_limit < bandwidth)
1176			return MODE_BAD;
1177	}
1178
1179	return MODE_OK;
1180}
1181
1182int dispc_vp_enable_clk(struct dispc_device *dispc, u32 hw_videoport)
1183{
1184	int ret = clk_prepare_enable(dispc->vp_clk[hw_videoport]);
1185
1186	if (ret)
1187		dev_err(dispc->dev, "%s: enabling clk failed: %d\n", __func__,
1188			ret);
1189
1190	return ret;
1191}
1192
1193void dispc_vp_disable_clk(struct dispc_device *dispc, u32 hw_videoport)
1194{
1195	clk_disable_unprepare(dispc->vp_clk[hw_videoport]);
1196}
1197
1198/*
1199 * Calculate the percentage difference between the requested pixel clock rate
1200 * and the effective rate resulting from calculating the clock divider value.
1201 */
1202static
1203unsigned int dispc_pclk_diff(unsigned long rate, unsigned long real_rate)
1204{
1205	int r = rate / 100, rr = real_rate / 100;
1206
1207	return (unsigned int)(abs(((rr - r) * 100) / r));
1208}
1209
1210int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport,
1211			  unsigned long rate)
1212{
1213	int r;
1214	unsigned long new_rate;
1215
1216	r = clk_set_rate(dispc->vp_clk[hw_videoport], rate);
1217	if (r) {
1218		dev_err(dispc->dev, "vp%d: failed to set clk rate to %lu\n",
1219			hw_videoport, rate);
1220		return r;
1221	}
1222
1223	new_rate = clk_get_rate(dispc->vp_clk[hw_videoport]);
1224
1225	if (dispc_pclk_diff(rate, new_rate) > 5)
1226		dev_warn(dispc->dev,
1227			 "vp%d: Clock rate %lu differs over 5%% from requested %lu\n",
1228			 hw_videoport, new_rate, rate);
1229
1230	dev_dbg(dispc->dev, "vp%d: new rate %lu Hz (requested %lu Hz)\n",
1231		hw_videoport, clk_get_rate(dispc->vp_clk[hw_videoport]), rate);
1232
1233	return 0;
1234}
1235
1236/* OVR */
1237static void dispc_k2g_ovr_set_plane(struct dispc_device *dispc,
1238				    u32 hw_plane, u32 hw_videoport,
1239				    u32 x, u32 y, u32 layer)
1240{
1241	/* On k2g there is only one plane and no need for ovr */
1242	dispc_vid_write(dispc, hw_plane, DISPC_VID_K2G_POSITION,
1243			x | (y << 16));
1244}
1245
1246static void dispc_am65x_ovr_set_plane(struct dispc_device *dispc,
1247				      u32 hw_plane, u32 hw_videoport,
1248				      u32 x, u32 y, u32 layer)
1249{
1250	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
1251			hw_plane, 4, 1);
1252	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
1253			x, 17, 6);
1254	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
1255			y, 30, 19);
1256}
1257
1258static void dispc_j721e_ovr_set_plane(struct dispc_device *dispc,
1259				      u32 hw_plane, u32 hw_videoport,
1260				      u32 x, u32 y, u32 layer)
1261{
1262	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
1263			hw_plane, 4, 1);
1264	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(layer),
1265			x, 13, 0);
1266	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(layer),
1267			y, 29, 16);
1268}
1269
1270void dispc_ovr_set_plane(struct dispc_device *dispc, u32 hw_plane,
1271			 u32 hw_videoport, u32 x, u32 y, u32 layer)
1272{
1273	switch (dispc->feat->subrev) {
1274	case DISPC_K2G:
1275		dispc_k2g_ovr_set_plane(dispc, hw_plane, hw_videoport,
1276					x, y, layer);
1277		break;
1278	case DISPC_AM65X:
1279		dispc_am65x_ovr_set_plane(dispc, hw_plane, hw_videoport,
1280					  x, y, layer);
1281		break;
1282	case DISPC_J721E:
1283		dispc_j721e_ovr_set_plane(dispc, hw_plane, hw_videoport,
1284					  x, y, layer);
1285		break;
1286	default:
1287		WARN_ON(1);
1288		break;
1289	}
1290}
1291
1292void dispc_ovr_enable_layer(struct dispc_device *dispc,
1293			    u32 hw_videoport, u32 layer, bool enable)
1294{
1295	if (dispc->feat->subrev == DISPC_K2G)
1296		return;
1297
1298	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
1299			!!enable, 0, 0);
1300}
1301
1302/* CSC */
1303enum csc_ctm {
1304	CSC_RR, CSC_RG, CSC_RB,
1305	CSC_GR, CSC_GG, CSC_GB,
1306	CSC_BR, CSC_BG, CSC_BB,
1307};
1308
1309enum csc_yuv2rgb {
1310	CSC_RY, CSC_RCB, CSC_RCR,
1311	CSC_GY, CSC_GCB, CSC_GCR,
1312	CSC_BY, CSC_BCB, CSC_BCR,
1313};
1314
1315enum csc_rgb2yuv {
1316	CSC_YR,  CSC_YG,  CSC_YB,
1317	CSC_CBR, CSC_CBG, CSC_CBB,
1318	CSC_CRR, CSC_CRG, CSC_CRB,
1319};
1320
1321struct dispc_csc_coef {
1322	void (*to_regval)(const struct dispc_csc_coef *csc, u32 *regval);
1323	int m[9];
1324	int preoffset[3];
1325	int postoffset[3];
1326	enum { CLIP_LIMITED_RANGE = 0, CLIP_FULL_RANGE = 1, } cliping;
1327	const char *name;
1328};
1329
1330#define DISPC_CSC_REGVAL_LEN 8
1331
1332static
1333void dispc_csc_offset_regval(const struct dispc_csc_coef *csc, u32 *regval)
1334{
1335#define OVAL(x, y) (FLD_VAL(x, 15, 3) | FLD_VAL(y, 31, 19))
1336	regval[5] = OVAL(csc->preoffset[0], csc->preoffset[1]);
1337	regval[6] = OVAL(csc->preoffset[2], csc->postoffset[0]);
1338	regval[7] = OVAL(csc->postoffset[1], csc->postoffset[2]);
1339#undef OVAL
1340}
1341
1342#define CVAL(x, y) (FLD_VAL(x, 10, 0) | FLD_VAL(y, 26, 16))
1343static
1344void dispc_csc_yuv2rgb_regval(const struct dispc_csc_coef *csc, u32 *regval)
1345{
1346	regval[0] = CVAL(csc->m[CSC_RY], csc->m[CSC_RCR]);
1347	regval[1] = CVAL(csc->m[CSC_RCB], csc->m[CSC_GY]);
1348	regval[2] = CVAL(csc->m[CSC_GCR], csc->m[CSC_GCB]);
1349	regval[3] = CVAL(csc->m[CSC_BY], csc->m[CSC_BCR]);
1350	regval[4] = CVAL(csc->m[CSC_BCB], 0);
1351
1352	dispc_csc_offset_regval(csc, regval);
1353}
1354
1355__maybe_unused static
1356void dispc_csc_rgb2yuv_regval(const struct dispc_csc_coef *csc, u32 *regval)
1357{
1358	regval[0] = CVAL(csc->m[CSC_YR], csc->m[CSC_YG]);
1359	regval[1] = CVAL(csc->m[CSC_YB], csc->m[CSC_CRR]);
1360	regval[2] = CVAL(csc->m[CSC_CRG], csc->m[CSC_CRB]);
1361	regval[3] = CVAL(csc->m[CSC_CBR], csc->m[CSC_CBG]);
1362	regval[4] = CVAL(csc->m[CSC_CBB], 0);
1363
1364	dispc_csc_offset_regval(csc, regval);
1365}
1366
1367static void dispc_csc_cpr_regval(const struct dispc_csc_coef *csc,
1368				 u32 *regval)
1369{
1370	regval[0] = CVAL(csc->m[CSC_RR], csc->m[CSC_RG]);
1371	regval[1] = CVAL(csc->m[CSC_RB], csc->m[CSC_GR]);
1372	regval[2] = CVAL(csc->m[CSC_GG], csc->m[CSC_GB]);
1373	regval[3] = CVAL(csc->m[CSC_BR], csc->m[CSC_BG]);
1374	regval[4] = CVAL(csc->m[CSC_BB], 0);
1375
1376	dispc_csc_offset_regval(csc, regval);
1377}
1378
1379#undef CVAL
1380
1381static void dispc_k2g_vid_write_csc(struct dispc_device *dispc, u32 hw_plane,
1382				    const struct dispc_csc_coef *csc)
1383{
1384	static const u16 dispc_vid_csc_coef_reg[] = {
1385		DISPC_VID_CSC_COEF(0), DISPC_VID_CSC_COEF(1),
1386		DISPC_VID_CSC_COEF(2), DISPC_VID_CSC_COEF(3),
1387		DISPC_VID_CSC_COEF(4), DISPC_VID_CSC_COEF(5),
1388		DISPC_VID_CSC_COEF(6), /* K2G has no post offset support */
1389	};
1390	u32 regval[DISPC_CSC_REGVAL_LEN];
1391	unsigned int i;
1392
1393	csc->to_regval(csc, regval);
1394
1395	if (regval[7] != 0)
1396		dev_warn(dispc->dev, "%s: No post offset support for %s\n",
1397			 __func__, csc->name);
1398
1399	for (i = 0; i < ARRAY_SIZE(dispc_vid_csc_coef_reg); i++)
1400		dispc_vid_write(dispc, hw_plane, dispc_vid_csc_coef_reg[i],
1401				regval[i]);
1402}
1403
1404static void dispc_k3_vid_write_csc(struct dispc_device *dispc, u32 hw_plane,
1405				   const struct dispc_csc_coef *csc)
1406{
1407	static const u16 dispc_vid_csc_coef_reg[DISPC_CSC_REGVAL_LEN] = {
1408		DISPC_VID_CSC_COEF(0), DISPC_VID_CSC_COEF(1),
1409		DISPC_VID_CSC_COEF(2), DISPC_VID_CSC_COEF(3),
1410		DISPC_VID_CSC_COEF(4), DISPC_VID_CSC_COEF(5),
1411		DISPC_VID_CSC_COEF(6), DISPC_VID_CSC_COEF7,
1412	};
1413	u32 regval[DISPC_CSC_REGVAL_LEN];
1414	unsigned int i;
1415
1416	csc->to_regval(csc, regval);
1417
1418	for (i = 0; i < ARRAY_SIZE(dispc_vid_csc_coef_reg); i++)
1419		dispc_vid_write(dispc, hw_plane, dispc_vid_csc_coef_reg[i],
1420				regval[i]);
1421}
1422
1423/* YUV -> RGB, ITU-R BT.601, full range */
1424static const struct dispc_csc_coef csc_yuv2rgb_bt601_full = {
1425	dispc_csc_yuv2rgb_regval,
1426	{ 256,   0,  358,	/* ry, rcb, rcr |1.000  0.000  1.402|*/
1427	  256, -88, -182,	/* gy, gcb, gcr |1.000 -0.344 -0.714|*/
1428	  256, 452,    0, },	/* by, bcb, bcr |1.000  1.772  0.000|*/
1429	{    0, -2048, -2048, },	/* full range */
1430	{    0,     0,     0, },
1431	CLIP_FULL_RANGE,
1432	"BT.601 Full",
1433};
1434
1435/* YUV -> RGB, ITU-R BT.601, limited range */
1436static const struct dispc_csc_coef csc_yuv2rgb_bt601_lim = {
1437	dispc_csc_yuv2rgb_regval,
1438	{ 298,    0,  409,	/* ry, rcb, rcr |1.164  0.000  1.596|*/
1439	  298, -100, -208,	/* gy, gcb, gcr |1.164 -0.392 -0.813|*/
1440	  298,  516,    0, },	/* by, bcb, bcr |1.164  2.017  0.000|*/
1441	{ -256, -2048, -2048, },	/* limited range */
1442	{    0,     0,     0, },
1443	CLIP_FULL_RANGE,
1444	"BT.601 Limited",
1445};
1446
1447/* YUV -> RGB, ITU-R BT.709, full range */
1448static const struct dispc_csc_coef csc_yuv2rgb_bt709_full = {
1449	dispc_csc_yuv2rgb_regval,
1450	{ 256,	  0,  402,	/* ry, rcb, rcr |1.000	0.000  1.570|*/
1451	  256,  -48, -120,	/* gy, gcb, gcr |1.000 -0.187 -0.467|*/
1452	  256,  475,    0, },	/* by, bcb, bcr |1.000	1.856  0.000|*/
1453	{    0, -2048, -2048, },	/* full range */
1454	{    0,     0,     0, },
1455	CLIP_FULL_RANGE,
1456	"BT.709 Full",
1457};
1458
1459/* YUV -> RGB, ITU-R BT.709, limited range */
1460static const struct dispc_csc_coef csc_yuv2rgb_bt709_lim = {
1461	dispc_csc_yuv2rgb_regval,
1462	{ 298,    0,  459,	/* ry, rcb, rcr |1.164  0.000  1.793|*/
1463	  298,  -55, -136,	/* gy, gcb, gcr |1.164 -0.213 -0.533|*/
1464	  298,  541,    0, },	/* by, bcb, bcr |1.164  2.112  0.000|*/
1465	{ -256, -2048, -2048, },	/* limited range */
1466	{    0,     0,     0, },
1467	CLIP_FULL_RANGE,
1468	"BT.709 Limited",
1469};
1470
1471static const struct {
1472	enum drm_color_encoding encoding;
1473	enum drm_color_range range;
1474	const struct dispc_csc_coef *csc;
1475} dispc_csc_table[] = {
1476	{ DRM_COLOR_YCBCR_BT601, DRM_COLOR_YCBCR_FULL_RANGE,
1477	  &csc_yuv2rgb_bt601_full, },
1478	{ DRM_COLOR_YCBCR_BT601, DRM_COLOR_YCBCR_LIMITED_RANGE,
1479	  &csc_yuv2rgb_bt601_lim, },
1480	{ DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_FULL_RANGE,
1481	  &csc_yuv2rgb_bt709_full, },
1482	{ DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE,
1483	  &csc_yuv2rgb_bt709_lim, },
1484};
1485
1486static const
1487struct dispc_csc_coef *dispc_find_csc(enum drm_color_encoding encoding,
1488				      enum drm_color_range range)
1489{
1490	unsigned int i;
1491
1492	for (i = 0; i < ARRAY_SIZE(dispc_csc_table); i++) {
1493		if (dispc_csc_table[i].encoding == encoding &&
1494		    dispc_csc_table[i].range == range) {
1495			return dispc_csc_table[i].csc;
1496		}
1497	}
1498	return NULL;
1499}
1500
1501static void dispc_vid_csc_setup(struct dispc_device *dispc, u32 hw_plane,
1502				const struct drm_plane_state *state)
1503{
1504	const struct dispc_csc_coef *coef;
1505
1506	coef = dispc_find_csc(state->color_encoding, state->color_range);
1507	if (!coef) {
1508		dev_err(dispc->dev, "%s: CSC (%u,%u) not found\n",
1509			__func__, state->color_encoding, state->color_range);
1510		return;
1511	}
1512
1513	if (dispc->feat->subrev == DISPC_K2G)
1514		dispc_k2g_vid_write_csc(dispc, hw_plane, coef);
1515	else
1516		dispc_k3_vid_write_csc(dispc, hw_plane, coef);
1517}
1518
1519static void dispc_vid_csc_enable(struct dispc_device *dispc, u32 hw_plane,
1520				 bool enable)
1521{
1522	VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, !!enable, 9, 9);
1523}
1524
1525/* SCALER */
1526
1527static u32 dispc_calc_fir_inc(u32 in, u32 out)
1528{
1529	return (u32)div_u64(0x200000ull * in, out);
1530}
1531
1532enum dispc_vid_fir_coef_set {
1533	DISPC_VID_FIR_COEF_HORIZ,
1534	DISPC_VID_FIR_COEF_HORIZ_UV,
1535	DISPC_VID_FIR_COEF_VERT,
1536	DISPC_VID_FIR_COEF_VERT_UV,
1537};
1538
1539static void dispc_vid_write_fir_coefs(struct dispc_device *dispc,
1540				      u32 hw_plane,
1541				      enum dispc_vid_fir_coef_set coef_set,
1542				      const struct tidss_scale_coefs *coefs)
1543{
1544	static const u16 c0_regs[] = {
1545		[DISPC_VID_FIR_COEF_HORIZ] = DISPC_VID_FIR_COEFS_H0,
1546		[DISPC_VID_FIR_COEF_HORIZ_UV] = DISPC_VID_FIR_COEFS_H0_C,
1547		[DISPC_VID_FIR_COEF_VERT] = DISPC_VID_FIR_COEFS_V0,
1548		[DISPC_VID_FIR_COEF_VERT_UV] = DISPC_VID_FIR_COEFS_V0_C,
1549	};
1550
1551	static const u16 c12_regs[] = {
1552		[DISPC_VID_FIR_COEF_HORIZ] = DISPC_VID_FIR_COEFS_H12,
1553		[DISPC_VID_FIR_COEF_HORIZ_UV] = DISPC_VID_FIR_COEFS_H12_C,
1554		[DISPC_VID_FIR_COEF_VERT] = DISPC_VID_FIR_COEFS_V12,
1555		[DISPC_VID_FIR_COEF_VERT_UV] = DISPC_VID_FIR_COEFS_V12_C,
1556	};
1557
1558	const u16 c0_base = c0_regs[coef_set];
1559	const u16 c12_base = c12_regs[coef_set];
1560	int phase;
1561
1562	if (!coefs) {
1563		dev_err(dispc->dev, "%s: No coefficients given.\n", __func__);
1564		return;
1565	}
1566
1567	for (phase = 0; phase <= 8; ++phase) {
1568		u16 reg = c0_base + phase * 4;
1569		u16 c0 = coefs->c0[phase];
1570
1571		dispc_vid_write(dispc, hw_plane, reg, c0);
1572	}
1573
1574	for (phase = 0; phase <= 15; ++phase) {
1575		u16 reg = c12_base + phase * 4;
1576		s16 c1, c2;
1577		u32 c12;
1578
1579		c1 = coefs->c1[phase];
1580		c2 = coefs->c2[phase];
1581		c12 = FLD_VAL(c1, 19, 10) | FLD_VAL(c2, 29, 20);
1582
1583		dispc_vid_write(dispc, hw_plane, reg, c12);
1584	}
1585}
1586
1587static bool dispc_fourcc_is_yuv(u32 fourcc)
1588{
1589	switch (fourcc) {
1590	case DRM_FORMAT_YUYV:
1591	case DRM_FORMAT_UYVY:
1592	case DRM_FORMAT_NV12:
1593		return true;
1594	default:
1595		return false;
1596	}
1597}
1598
1599struct dispc_scaling_params {
1600	int xinc, yinc;
1601	u32 in_w, in_h, in_w_uv, in_h_uv;
1602	u32 fir_xinc, fir_yinc, fir_xinc_uv, fir_yinc_uv;
1603	bool scale_x, scale_y;
1604	const struct tidss_scale_coefs *xcoef, *ycoef, *xcoef_uv, *ycoef_uv;
1605	bool five_taps;
1606};
1607
1608static int dispc_vid_calc_scaling(struct dispc_device *dispc,
1609				  const struct drm_plane_state *state,
1610				  struct dispc_scaling_params *sp,
1611				  bool lite_plane)
1612{
1613	const struct dispc_features_scaling *f = &dispc->feat->scaling;
1614	u32 fourcc = state->fb->format->format;
1615	u32 in_width_max_5tap = f->in_width_max_5tap_rgb;
1616	u32 in_width_max_3tap = f->in_width_max_3tap_rgb;
1617	u32 downscale_limit;
1618	u32 in_width_max;
1619
1620	memset(sp, 0, sizeof(*sp));
1621	sp->xinc = 1;
1622	sp->yinc = 1;
1623	sp->in_w = state->src_w >> 16;
1624	sp->in_w_uv = sp->in_w;
1625	sp->in_h = state->src_h >> 16;
1626	sp->in_h_uv = sp->in_h;
1627
1628	sp->scale_x = sp->in_w != state->crtc_w;
1629	sp->scale_y = sp->in_h != state->crtc_h;
1630
1631	if (dispc_fourcc_is_yuv(fourcc)) {
1632		in_width_max_5tap = f->in_width_max_5tap_yuv;
1633		in_width_max_3tap = f->in_width_max_3tap_yuv;
1634
1635		sp->in_w_uv >>= 1;
1636		sp->scale_x = true;
1637
1638		if (fourcc == DRM_FORMAT_NV12) {
1639			sp->in_h_uv >>= 1;
1640			sp->scale_y = true;
1641		}
1642	}
1643
1644	/* Skip the rest if no scaling is used */
1645	if ((!sp->scale_x && !sp->scale_y) || lite_plane)
1646		return 0;
1647
1648	if (sp->in_w > in_width_max_5tap) {
1649		sp->five_taps = false;
1650		in_width_max = in_width_max_3tap;
1651		downscale_limit = f->downscale_limit_3tap;
1652	} else {
1653		sp->five_taps = true;
1654		in_width_max = in_width_max_5tap;
1655		downscale_limit = f->downscale_limit_5tap;
1656	}
1657
1658	if (sp->scale_x) {
1659		sp->fir_xinc = dispc_calc_fir_inc(sp->in_w, state->crtc_w);
1660
1661		if (sp->fir_xinc < dispc_calc_fir_inc(1, f->upscale_limit)) {
1662			dev_dbg(dispc->dev,
1663				"%s: X-scaling factor %u/%u > %u\n",
1664				__func__, state->crtc_w, state->src_w >> 16,
1665				f->upscale_limit);
1666			return -EINVAL;
1667		}
1668
1669		if (sp->fir_xinc >= dispc_calc_fir_inc(downscale_limit, 1)) {
1670			sp->xinc = DIV_ROUND_UP(DIV_ROUND_UP(sp->in_w,
1671							     state->crtc_w),
1672						downscale_limit);
1673
1674			if (sp->xinc > f->xinc_max) {
1675				dev_dbg(dispc->dev,
1676					"%s: X-scaling factor %u/%u < 1/%u\n",
1677					__func__, state->crtc_w,
1678					state->src_w >> 16,
1679					downscale_limit * f->xinc_max);
1680				return -EINVAL;
1681			}
1682
1683			sp->in_w = (state->src_w >> 16) / sp->xinc;
1684		}
1685
1686		while (sp->in_w > in_width_max) {
1687			sp->xinc++;
1688			sp->in_w = (state->src_w >> 16) / sp->xinc;
1689		}
1690
1691		if (sp->xinc > f->xinc_max) {
1692			dev_dbg(dispc->dev,
1693				"%s: Too wide input buffer %u > %u\n", __func__,
1694				state->src_w >> 16, in_width_max * f->xinc_max);
1695			return -EINVAL;
1696		}
1697
1698		/*
1699		 * We need even line length for YUV formats. Decimation
1700		 * can lead to odd length, so we need to make it even
1701		 * again.
1702		 */
1703		if (dispc_fourcc_is_yuv(fourcc))
1704			sp->in_w &= ~1;
1705
1706		sp->fir_xinc = dispc_calc_fir_inc(sp->in_w, state->crtc_w);
1707	}
1708
1709	if (sp->scale_y) {
1710		sp->fir_yinc = dispc_calc_fir_inc(sp->in_h, state->crtc_h);
1711
1712		if (sp->fir_yinc < dispc_calc_fir_inc(1, f->upscale_limit)) {
1713			dev_dbg(dispc->dev,
1714				"%s: Y-scaling factor %u/%u > %u\n",
1715				__func__, state->crtc_h, state->src_h >> 16,
1716				f->upscale_limit);
1717			return -EINVAL;
1718		}
1719
1720		if (sp->fir_yinc >= dispc_calc_fir_inc(downscale_limit, 1)) {
1721			sp->yinc = DIV_ROUND_UP(DIV_ROUND_UP(sp->in_h,
1722							     state->crtc_h),
1723						downscale_limit);
1724
1725			sp->in_h /= sp->yinc;
1726			sp->fir_yinc = dispc_calc_fir_inc(sp->in_h,
1727							  state->crtc_h);
1728		}
1729	}
1730
1731	dev_dbg(dispc->dev,
1732		"%s: %ux%u decim %ux%u -> %ux%u firinc %u.%03ux%u.%03u taps %u -> %ux%u\n",
1733		__func__, state->src_w >> 16, state->src_h >> 16,
1734		sp->xinc, sp->yinc, sp->in_w, sp->in_h,
1735		sp->fir_xinc / 0x200000u,
1736		((sp->fir_xinc & 0x1FFFFFu) * 999u) / 0x1FFFFFu,
1737		sp->fir_yinc / 0x200000u,
1738		((sp->fir_yinc & 0x1FFFFFu) * 999u) / 0x1FFFFFu,
1739		sp->five_taps ? 5 : 3,
1740		state->crtc_w, state->crtc_h);
1741
1742	if (dispc_fourcc_is_yuv(fourcc)) {
1743		if (sp->scale_x) {
1744			sp->in_w_uv /= sp->xinc;
1745			sp->fir_xinc_uv = dispc_calc_fir_inc(sp->in_w_uv,
1746							     state->crtc_w);
1747			sp->xcoef_uv = tidss_get_scale_coefs(dispc->dev,
1748							     sp->fir_xinc_uv,
1749							     true);
1750		}
1751		if (sp->scale_y) {
1752			sp->in_h_uv /= sp->yinc;
1753			sp->fir_yinc_uv = dispc_calc_fir_inc(sp->in_h_uv,
1754							     state->crtc_h);
1755			sp->ycoef_uv = tidss_get_scale_coefs(dispc->dev,
1756							     sp->fir_yinc_uv,
1757							     sp->five_taps);
1758		}
1759	}
1760
1761	if (sp->scale_x)
1762		sp->xcoef = tidss_get_scale_coefs(dispc->dev, sp->fir_xinc,
1763						  true);
1764
1765	if (sp->scale_y)
1766		sp->ycoef = tidss_get_scale_coefs(dispc->dev, sp->fir_yinc,
1767						  sp->five_taps);
1768
1769	return 0;
1770}
1771
1772static void dispc_vid_set_scaling(struct dispc_device *dispc,
1773				  u32 hw_plane,
1774				  struct dispc_scaling_params *sp,
1775				  u32 fourcc)
1776{
1777	/* HORIZONTAL RESIZE ENABLE */
1778	VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES,
1779			sp->scale_x, 7, 7);
1780
1781	/* VERTICAL RESIZE ENABLE */
1782	VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES,
1783			sp->scale_y, 8, 8);
1784
1785	/* Skip the rest if no scaling is used */
1786	if (!sp->scale_x && !sp->scale_y)
1787		return;
1788
1789	/* VERTICAL 5-TAPS  */
1790	VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES,
1791			sp->five_taps, 21, 21);
1792
1793	if (dispc_fourcc_is_yuv(fourcc)) {
1794		if (sp->scale_x) {
1795			dispc_vid_write(dispc, hw_plane, DISPC_VID_FIRH2,
1796					sp->fir_xinc_uv);
1797			dispc_vid_write_fir_coefs(dispc, hw_plane,
1798						  DISPC_VID_FIR_COEF_HORIZ_UV,
1799						  sp->xcoef_uv);
1800		}
1801		if (sp->scale_y) {
1802			dispc_vid_write(dispc, hw_plane, DISPC_VID_FIRV2,
1803					sp->fir_yinc_uv);
1804			dispc_vid_write_fir_coefs(dispc, hw_plane,
1805						  DISPC_VID_FIR_COEF_VERT_UV,
1806						  sp->ycoef_uv);
1807		}
1808	}
1809
1810	if (sp->scale_x) {
1811		dispc_vid_write(dispc, hw_plane, DISPC_VID_FIRH, sp->fir_xinc);
1812		dispc_vid_write_fir_coefs(dispc, hw_plane,
1813					  DISPC_VID_FIR_COEF_HORIZ,
1814					  sp->xcoef);
1815	}
1816
1817	if (sp->scale_y) {
1818		dispc_vid_write(dispc, hw_plane, DISPC_VID_FIRV, sp->fir_yinc);
1819		dispc_vid_write_fir_coefs(dispc, hw_plane,
1820					  DISPC_VID_FIR_COEF_VERT, sp->ycoef);
1821	}
1822}
1823
1824/* OTHER */
1825
1826static const struct {
1827	u32 fourcc;
1828	u8 dss_code;
1829} dispc_color_formats[] = {
1830	{ DRM_FORMAT_ARGB4444, 0x0, },
1831	{ DRM_FORMAT_ABGR4444, 0x1, },
1832	{ DRM_FORMAT_RGBA4444, 0x2, },
1833
1834	{ DRM_FORMAT_RGB565, 0x3, },
1835	{ DRM_FORMAT_BGR565, 0x4, },
1836
1837	{ DRM_FORMAT_ARGB1555, 0x5, },
1838	{ DRM_FORMAT_ABGR1555, 0x6, },
1839
1840	{ DRM_FORMAT_ARGB8888, 0x7, },
1841	{ DRM_FORMAT_ABGR8888, 0x8, },
1842	{ DRM_FORMAT_RGBA8888, 0x9, },
1843	{ DRM_FORMAT_BGRA8888, 0xa, },
1844
1845	{ DRM_FORMAT_RGB888, 0xb, },
1846	{ DRM_FORMAT_BGR888, 0xc, },
1847
1848	{ DRM_FORMAT_ARGB2101010, 0xe, },
1849	{ DRM_FORMAT_ABGR2101010, 0xf, },
1850
1851	{ DRM_FORMAT_XRGB4444, 0x20, },
1852	{ DRM_FORMAT_XBGR4444, 0x21, },
1853	{ DRM_FORMAT_RGBX4444, 0x22, },
1854
1855	{ DRM_FORMAT_ARGB1555, 0x25, },
1856	{ DRM_FORMAT_ABGR1555, 0x26, },
1857
1858	{ DRM_FORMAT_XRGB8888, 0x27, },
1859	{ DRM_FORMAT_XBGR8888, 0x28, },
1860	{ DRM_FORMAT_RGBX8888, 0x29, },
1861	{ DRM_FORMAT_BGRX8888, 0x2a, },
1862
1863	{ DRM_FORMAT_XRGB2101010, 0x2e, },
1864	{ DRM_FORMAT_XBGR2101010, 0x2f, },
1865
1866	{ DRM_FORMAT_YUYV, 0x3e, },
1867	{ DRM_FORMAT_UYVY, 0x3f, },
1868
1869	{ DRM_FORMAT_NV12, 0x3d, },
1870};
1871
1872static void dispc_plane_set_pixel_format(struct dispc_device *dispc,
1873					 u32 hw_plane, u32 fourcc)
1874{
1875	unsigned int i;
1876
1877	for (i = 0; i < ARRAY_SIZE(dispc_color_formats); ++i) {
1878		if (dispc_color_formats[i].fourcc == fourcc) {
1879			VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES,
1880					dispc_color_formats[i].dss_code,
1881					6, 1);
1882			return;
1883		}
1884	}
1885
1886	WARN_ON(1);
1887}
1888
1889const u32 *dispc_plane_formats(struct dispc_device *dispc, unsigned int *len)
1890{
1891	WARN_ON(!dispc->fourccs);
1892
1893	*len = dispc->num_fourccs;
1894
1895	return dispc->fourccs;
1896}
1897
1898static s32 pixinc(int pixels, u8 ps)
1899{
1900	if (pixels == 1)
1901		return 1;
1902	else if (pixels > 1)
1903		return 1 + (pixels - 1) * ps;
1904	else if (pixels < 0)
1905		return 1 - (-pixels + 1) * ps;
1906
1907	WARN_ON(1);
1908	return 0;
1909}
1910
1911int dispc_plane_check(struct dispc_device *dispc, u32 hw_plane,
1912		      const struct drm_plane_state *state,
1913		      u32 hw_videoport)
1914{
1915	bool lite = dispc->feat->vid_lite[hw_plane];
1916	u32 fourcc = state->fb->format->format;
1917	bool need_scaling = state->src_w >> 16 != state->crtc_w ||
1918		state->src_h >> 16 != state->crtc_h;
1919	struct dispc_scaling_params scaling;
1920	int ret;
1921
1922	if (dispc_fourcc_is_yuv(fourcc)) {
1923		if (!dispc_find_csc(state->color_encoding,
1924				    state->color_range)) {
1925			dev_dbg(dispc->dev,
1926				"%s: Unsupported CSC (%u,%u) for HW plane %u\n",
1927				__func__, state->color_encoding,
1928				state->color_range, hw_plane);
1929			return -EINVAL;
1930		}
1931	}
1932
1933	if (need_scaling) {
1934		if (lite) {
1935			dev_dbg(dispc->dev,
1936				"%s: Lite plane %u can't scale %ux%u!=%ux%u\n",
1937				__func__, hw_plane,
1938				state->src_w >> 16, state->src_h >> 16,
1939				state->crtc_w, state->crtc_h);
1940			return -EINVAL;
1941		}
1942		ret = dispc_vid_calc_scaling(dispc, state, &scaling, false);
1943		if (ret)
1944			return ret;
1945	}
1946
1947	return 0;
1948}
1949
1950static
1951dma_addr_t dispc_plane_state_paddr(const struct drm_plane_state *state)
1952{
1953	struct drm_framebuffer *fb = state->fb;
1954	struct drm_gem_cma_object *gem;
1955	u32 x = state->src_x >> 16;
1956	u32 y = state->src_y >> 16;
1957
1958	gem = drm_fb_cma_get_gem_obj(state->fb, 0);
1959
1960	return gem->paddr + fb->offsets[0] + x * fb->format->cpp[0] +
1961		y * fb->pitches[0];
1962}
1963
1964static
1965dma_addr_t dispc_plane_state_p_uv_addr(const struct drm_plane_state *state)
1966{
1967	struct drm_framebuffer *fb = state->fb;
1968	struct drm_gem_cma_object *gem;
1969	u32 x = state->src_x >> 16;
1970	u32 y = state->src_y >> 16;
1971
1972	if (WARN_ON(state->fb->format->num_planes != 2))
1973		return 0;
1974
1975	gem = drm_fb_cma_get_gem_obj(fb, 1);
1976
1977	return gem->paddr + fb->offsets[1] +
1978		(x * fb->format->cpp[1] / fb->format->hsub) +
1979		(y * fb->pitches[1] / fb->format->vsub);
1980}
1981
1982int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane,
1983		      const struct drm_plane_state *state,
1984		      u32 hw_videoport)
1985{
1986	bool lite = dispc->feat->vid_lite[hw_plane];
1987	u32 fourcc = state->fb->format->format;
1988	u16 cpp = state->fb->format->cpp[0];
1989	u32 fb_width = state->fb->pitches[0] / cpp;
1990	dma_addr_t paddr = dispc_plane_state_paddr(state);
1991	struct dispc_scaling_params scale;
1992
1993	dispc_vid_calc_scaling(dispc, state, &scale, lite);
1994
1995	dispc_plane_set_pixel_format(dispc, hw_plane, fourcc);
1996
1997	dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_0, paddr & 0xffffffff);
1998	dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_EXT_0, (u64)paddr >> 32);
1999	dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_1, paddr & 0xffffffff);
2000	dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_EXT_1, (u64)paddr >> 32);
2001
2002	dispc_vid_write(dispc, hw_plane, DISPC_VID_PICTURE_SIZE,
2003			(scale.in_w - 1) | ((scale.in_h - 1) << 16));
2004
2005	/* For YUV422 format we use the macropixel size for pixel inc */
2006	if (fourcc == DRM_FORMAT_YUYV || fourcc == DRM_FORMAT_UYVY)
2007		dispc_vid_write(dispc, hw_plane, DISPC_VID_PIXEL_INC,
2008				pixinc(scale.xinc, cpp * 2));
2009	else
2010		dispc_vid_write(dispc, hw_plane, DISPC_VID_PIXEL_INC,
2011				pixinc(scale.xinc, cpp));
2012
2013	dispc_vid_write(dispc, hw_plane, DISPC_VID_ROW_INC,
2014			pixinc(1 + (scale.yinc * fb_width -
2015				    scale.xinc * scale.in_w),
2016			       cpp));
2017
2018	if (state->fb->format->num_planes == 2) {
2019		u16 cpp_uv = state->fb->format->cpp[1];
2020		u32 fb_width_uv = state->fb->pitches[1] / cpp_uv;
2021		dma_addr_t p_uv_addr = dispc_plane_state_p_uv_addr(state);
2022
2023		dispc_vid_write(dispc, hw_plane,
2024				DISPC_VID_BA_UV_0, p_uv_addr & 0xffffffff);
2025		dispc_vid_write(dispc, hw_plane,
2026				DISPC_VID_BA_UV_EXT_0, (u64)p_uv_addr >> 32);
2027		dispc_vid_write(dispc, hw_plane,
2028				DISPC_VID_BA_UV_1, p_uv_addr & 0xffffffff);
2029		dispc_vid_write(dispc, hw_plane,
2030				DISPC_VID_BA_UV_EXT_1, (u64)p_uv_addr >> 32);
2031
2032		dispc_vid_write(dispc, hw_plane, DISPC_VID_ROW_INC_UV,
2033				pixinc(1 + (scale.yinc * fb_width_uv -
2034					    scale.xinc * scale.in_w_uv),
2035				       cpp_uv));
2036	}
2037
2038	if (!lite) {
2039		dispc_vid_write(dispc, hw_plane, DISPC_VID_SIZE,
2040				(state->crtc_w - 1) |
2041				((state->crtc_h - 1) << 16));
2042
2043		dispc_vid_set_scaling(dispc, hw_plane, &scale, fourcc);
2044	}
2045
2046	/* enable YUV->RGB color conversion */
2047	if (dispc_fourcc_is_yuv(fourcc)) {
2048		dispc_vid_csc_setup(dispc, hw_plane, state);
2049		dispc_vid_csc_enable(dispc, hw_plane, true);
2050	} else {
2051		dispc_vid_csc_enable(dispc, hw_plane, false);
2052	}
2053
2054	dispc_vid_write(dispc, hw_plane, DISPC_VID_GLOBAL_ALPHA,
2055			0xFF & (state->alpha >> 8));
2056
2057	if (state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
2058		VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 1,
2059				28, 28);
2060	else
2061		VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 0,
2062				28, 28);
2063
2064	return 0;
2065}
2066
2067int dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable)
2068{
2069	VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, !!enable, 0, 0);
2070
2071	return 0;
2072}
2073
2074static u32 dispc_vid_get_fifo_size(struct dispc_device *dispc, u32 hw_plane)
2075{
2076	return VID_REG_GET(dispc, hw_plane, DISPC_VID_BUF_SIZE_STATUS, 15, 0);
2077}
2078
2079static void dispc_vid_set_mflag_threshold(struct dispc_device *dispc,
2080					  u32 hw_plane, u32 low, u32 high)
2081{
2082	dispc_vid_write(dispc, hw_plane, DISPC_VID_MFLAG_THRESHOLD,
2083			FLD_VAL(high, 31, 16) | FLD_VAL(low, 15, 0));
2084}
2085
2086static void dispc_vid_set_buf_threshold(struct dispc_device *dispc,
2087					u32 hw_plane, u32 low, u32 high)
2088{
2089	dispc_vid_write(dispc, hw_plane, DISPC_VID_BUF_THRESHOLD,
2090			FLD_VAL(high, 31, 16) | FLD_VAL(low, 15, 0));
2091}
2092
2093static void dispc_k2g_plane_init(struct dispc_device *dispc)
2094{
2095	unsigned int hw_plane;
2096
2097	dev_dbg(dispc->dev, "%s()\n", __func__);
2098
2099	/* MFLAG_CTRL = ENABLED */
2100	REG_FLD_MOD(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE, 2, 1, 0);
2101	/* MFLAG_START = MFLAGNORMALSTARTMODE */
2102	REG_FLD_MOD(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE, 0, 6, 6);
2103
2104	for (hw_plane = 0; hw_plane < dispc->feat->num_planes; hw_plane++) {
2105		u32 size = dispc_vid_get_fifo_size(dispc, hw_plane);
2106		u32 thr_low, thr_high;
2107		u32 mflag_low, mflag_high;
2108		u32 preload;
2109
2110		thr_high = size - 1;
2111		thr_low = size / 2;
2112
2113		mflag_high = size * 2 / 3;
2114		mflag_low = size / 3;
2115
2116		preload = thr_low;
2117
2118		dev_dbg(dispc->dev,
2119			"%s: bufsize %u, buf_threshold %u/%u, mflag threshold %u/%u preload %u\n",
2120			dispc->feat->vid_name[hw_plane],
2121			size,
2122			thr_high, thr_low,
2123			mflag_high, mflag_low,
2124			preload);
2125
2126		dispc_vid_set_buf_threshold(dispc, hw_plane,
2127					    thr_low, thr_high);
2128		dispc_vid_set_mflag_threshold(dispc, hw_plane,
2129					      mflag_low, mflag_high);
2130
2131		dispc_vid_write(dispc, hw_plane, DISPC_VID_PRELOAD, preload);
2132
2133		/*
2134		 * Prefetch up to fifo high-threshold value to minimize the
2135		 * possibility of underflows. Note that this means the PRELOAD
2136		 * register is ignored.
2137		 */
2138		VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 1,
2139				19, 19);
2140	}
2141}
2142
2143static void dispc_k3_plane_init(struct dispc_device *dispc)
2144{
2145	unsigned int hw_plane;
2146	u32 cba_lo_pri = 1;
2147	u32 cba_hi_pri = 0;
2148
2149	dev_dbg(dispc->dev, "%s()\n", __func__);
2150
2151	REG_FLD_MOD(dispc, DSS_CBA_CFG, cba_lo_pri, 2, 0);
2152	REG_FLD_MOD(dispc, DSS_CBA_CFG, cba_hi_pri, 5, 3);
2153
2154	/* MFLAG_CTRL = ENABLED */
2155	REG_FLD_MOD(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE, 2, 1, 0);
2156	/* MFLAG_START = MFLAGNORMALSTARTMODE */
2157	REG_FLD_MOD(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE, 0, 6, 6);
2158
2159	for (hw_plane = 0; hw_plane < dispc->feat->num_planes; hw_plane++) {
2160		u32 size = dispc_vid_get_fifo_size(dispc, hw_plane);
2161		u32 thr_low, thr_high;
2162		u32 mflag_low, mflag_high;
2163		u32 preload;
2164
2165		thr_high = size - 1;
2166		thr_low = size / 2;
2167
2168		mflag_high = size * 2 / 3;
2169		mflag_low = size / 3;
2170
2171		preload = thr_low;
2172
2173		dev_dbg(dispc->dev,
2174			"%s: bufsize %u, buf_threshold %u/%u, mflag threshold %u/%u preload %u\n",
2175			dispc->feat->vid_name[hw_plane],
2176			size,
2177			thr_high, thr_low,
2178			mflag_high, mflag_low,
2179			preload);
2180
2181		dispc_vid_set_buf_threshold(dispc, hw_plane,
2182					    thr_low, thr_high);
2183		dispc_vid_set_mflag_threshold(dispc, hw_plane,
2184					      mflag_low, mflag_high);
2185
2186		dispc_vid_write(dispc, hw_plane, DISPC_VID_PRELOAD, preload);
2187
2188		/* Prefech up to PRELOAD value */
2189		VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 0,
2190				19, 19);
2191	}
2192}
2193
2194static void dispc_plane_init(struct dispc_device *dispc)
2195{
2196	switch (dispc->feat->subrev) {
2197	case DISPC_K2G:
2198		dispc_k2g_plane_init(dispc);
2199		break;
2200	case DISPC_AM65X:
2201	case DISPC_J721E:
2202		dispc_k3_plane_init(dispc);
2203		break;
2204	default:
2205		WARN_ON(1);
2206	}
2207}
2208
2209static void dispc_vp_init(struct dispc_device *dispc)
2210{
2211	unsigned int i;
2212
2213	dev_dbg(dispc->dev, "%s()\n", __func__);
2214
2215	/* Enable the gamma Shadow bit-field for all VPs*/
2216	for (i = 0; i < dispc->feat->num_vps; i++)
2217		VP_REG_FLD_MOD(dispc, i, DISPC_VP_CONFIG, 1, 2, 2);
2218}
2219
2220static void dispc_initial_config(struct dispc_device *dispc)
2221{
2222	dispc_plane_init(dispc);
2223	dispc_vp_init(dispc);
2224
2225	/* Note: Hardcoded DPI routing on J721E for now */
2226	if (dispc->feat->subrev == DISPC_J721E) {
2227		dispc_write(dispc, DISPC_CONNECTIONS,
2228			    FLD_VAL(2, 3, 0) |		/* VP1 to DPI0 */
2229			    FLD_VAL(8, 7, 4)		/* VP3 to DPI1 */
2230			);
2231	}
2232}
2233
2234static void dispc_k2g_vp_write_gamma_table(struct dispc_device *dispc,
2235					   u32 hw_videoport)
2236{
2237	u32 *table = dispc->vp_data[hw_videoport].gamma_table;
2238	u32 hwlen = dispc->feat->vp_feat.color.gamma_size;
2239	unsigned int i;
2240
2241	dev_dbg(dispc->dev, "%s: hw_videoport %d\n", __func__, hw_videoport);
2242
2243	if (WARN_ON(dispc->feat->vp_feat.color.gamma_type != TIDSS_GAMMA_8BIT))
2244		return;
2245
2246	for (i = 0; i < hwlen; ++i) {
2247		u32 v = table[i];
2248
2249		v |= i << 24;
2250
2251		dispc_vp_write(dispc, hw_videoport, DISPC_VP_K2G_GAMMA_TABLE,
2252			       v);
2253	}
2254}
2255
2256static void dispc_am65x_vp_write_gamma_table(struct dispc_device *dispc,
2257					     u32 hw_videoport)
2258{
2259	u32 *table = dispc->vp_data[hw_videoport].gamma_table;
2260	u32 hwlen = dispc->feat->vp_feat.color.gamma_size;
2261	unsigned int i;
2262
2263	dev_dbg(dispc->dev, "%s: hw_videoport %d\n", __func__, hw_videoport);
2264
2265	if (WARN_ON(dispc->feat->vp_feat.color.gamma_type != TIDSS_GAMMA_8BIT))
2266		return;
2267
2268	for (i = 0; i < hwlen; ++i) {
2269		u32 v = table[i];
2270
2271		v |= i << 24;
2272
2273		dispc_vp_write(dispc, hw_videoport, DISPC_VP_GAMMA_TABLE, v);
2274	}
2275}
2276
2277static void dispc_j721e_vp_write_gamma_table(struct dispc_device *dispc,
2278					     u32 hw_videoport)
2279{
2280	u32 *table = dispc->vp_data[hw_videoport].gamma_table;
2281	u32 hwlen = dispc->feat->vp_feat.color.gamma_size;
2282	unsigned int i;
2283
2284	dev_dbg(dispc->dev, "%s: hw_videoport %d\n", __func__, hw_videoport);
2285
2286	if (WARN_ON(dispc->feat->vp_feat.color.gamma_type != TIDSS_GAMMA_10BIT))
2287		return;
2288
2289	for (i = 0; i < hwlen; ++i) {
2290		u32 v = table[i];
2291
2292		if (i == 0)
2293			v |= 1 << 31;
2294
2295		dispc_vp_write(dispc, hw_videoport, DISPC_VP_GAMMA_TABLE, v);
2296	}
2297}
2298
2299static void dispc_vp_write_gamma_table(struct dispc_device *dispc,
2300				       u32 hw_videoport)
2301{
2302	switch (dispc->feat->subrev) {
2303	case DISPC_K2G:
2304		dispc_k2g_vp_write_gamma_table(dispc, hw_videoport);
2305		break;
2306	case DISPC_AM65X:
2307		dispc_am65x_vp_write_gamma_table(dispc, hw_videoport);
2308		break;
2309	case DISPC_J721E:
2310		dispc_j721e_vp_write_gamma_table(dispc, hw_videoport);
2311		break;
2312	default:
2313		WARN_ON(1);
2314		break;
2315	}
2316}
2317
2318static const struct drm_color_lut dispc_vp_gamma_default_lut[] = {
2319	{ .red = 0, .green = 0, .blue = 0, },
2320	{ .red = U16_MAX, .green = U16_MAX, .blue = U16_MAX, },
2321};
2322
2323static void dispc_vp_set_gamma(struct dispc_device *dispc,
2324			       u32 hw_videoport,
2325			       const struct drm_color_lut *lut,
2326			       unsigned int length)
2327{
2328	u32 *table = dispc->vp_data[hw_videoport].gamma_table;
2329	u32 hwlen = dispc->feat->vp_feat.color.gamma_size;
2330	u32 hwbits;
2331	unsigned int i;
2332
2333	dev_dbg(dispc->dev, "%s: hw_videoport %d, lut len %u, hw len %u\n",
2334		__func__, hw_videoport, length, hwlen);
2335
2336	if (dispc->feat->vp_feat.color.gamma_type == TIDSS_GAMMA_10BIT)
2337		hwbits = 10;
2338	else
2339		hwbits = 8;
2340
2341	if (!lut || length < 2) {
2342		lut = dispc_vp_gamma_default_lut;
2343		length = ARRAY_SIZE(dispc_vp_gamma_default_lut);
2344	}
2345
2346	for (i = 0; i < length - 1; ++i) {
2347		unsigned int first = i * (hwlen - 1) / (length - 1);
2348		unsigned int last = (i + 1) * (hwlen - 1) / (length - 1);
2349		unsigned int w = last - first;
2350		u16 r, g, b;
2351		unsigned int j;
2352
2353		if (w == 0)
2354			continue;
2355
2356		for (j = 0; j <= w; j++) {
2357			r = (lut[i].red * (w - j) + lut[i + 1].red * j) / w;
2358			g = (lut[i].green * (w - j) + lut[i + 1].green * j) / w;
2359			b = (lut[i].blue * (w - j) + lut[i + 1].blue * j) / w;
2360
2361			r >>= 16 - hwbits;
2362			g >>= 16 - hwbits;
2363			b >>= 16 - hwbits;
2364
2365			table[first + j] = (r << (hwbits * 2)) |
2366				(g << hwbits) | b;
2367		}
2368	}
2369
2370	dispc_vp_write_gamma_table(dispc, hw_videoport);
2371}
2372
2373static s16 dispc_S31_32_to_s2_8(s64 coef)
2374{
2375	u64 sign_bit = 1ULL << 63;
2376	u64 cbits = (u64)coef;
2377	s16 ret;
2378
2379	if (cbits & sign_bit)
2380		ret = -clamp_val(((cbits & ~sign_bit) >> 24), 0, 0x200);
2381	else
2382		ret = clamp_val(((cbits & ~sign_bit) >> 24), 0, 0x1FF);
2383
2384	return ret;
2385}
2386
2387static void dispc_k2g_cpr_from_ctm(const struct drm_color_ctm *ctm,
2388				   struct dispc_csc_coef *cpr)
2389{
2390	memset(cpr, 0, sizeof(*cpr));
2391
2392	cpr->to_regval = dispc_csc_cpr_regval;
2393	cpr->m[CSC_RR] = dispc_S31_32_to_s2_8(ctm->matrix[0]);
2394	cpr->m[CSC_RG] = dispc_S31_32_to_s2_8(ctm->matrix[1]);
2395	cpr->m[CSC_RB] = dispc_S31_32_to_s2_8(ctm->matrix[2]);
2396	cpr->m[CSC_GR] = dispc_S31_32_to_s2_8(ctm->matrix[3]);
2397	cpr->m[CSC_GG] = dispc_S31_32_to_s2_8(ctm->matrix[4]);
2398	cpr->m[CSC_GB] = dispc_S31_32_to_s2_8(ctm->matrix[5]);
2399	cpr->m[CSC_BR] = dispc_S31_32_to_s2_8(ctm->matrix[6]);
2400	cpr->m[CSC_BG] = dispc_S31_32_to_s2_8(ctm->matrix[7]);
2401	cpr->m[CSC_BB] = dispc_S31_32_to_s2_8(ctm->matrix[8]);
2402}
2403
2404#define CVAL(xR, xG, xB) (FLD_VAL(xR, 9, 0) | FLD_VAL(xG, 20, 11) |	\
2405			  FLD_VAL(xB, 31, 22))
2406
2407static void dispc_k2g_vp_csc_cpr_regval(const struct dispc_csc_coef *csc,
2408					u32 *regval)
2409{
2410	regval[0] = CVAL(csc->m[CSC_BB], csc->m[CSC_BG], csc->m[CSC_BR]);
2411	regval[1] = CVAL(csc->m[CSC_GB], csc->m[CSC_GG], csc->m[CSC_GR]);
2412	regval[2] = CVAL(csc->m[CSC_RB], csc->m[CSC_RG], csc->m[CSC_RR]);
2413}
2414
2415#undef CVAL
2416
2417static void dispc_k2g_vp_write_csc(struct dispc_device *dispc, u32 hw_videoport,
2418				   const struct dispc_csc_coef *csc)
2419{
2420	static const u16 dispc_vp_cpr_coef_reg[] = {
2421		DISPC_VP_CSC_COEF0, DISPC_VP_CSC_COEF1, DISPC_VP_CSC_COEF2,
2422		/* K2G CPR is packed to three registers. */
2423	};
2424	u32 regval[DISPC_CSC_REGVAL_LEN];
2425	unsigned int i;
2426
2427	dispc_k2g_vp_csc_cpr_regval(csc, regval);
2428
2429	for (i = 0; i < ARRAY_SIZE(dispc_vp_cpr_coef_reg); i++)
2430		dispc_vp_write(dispc, hw_videoport, dispc_vp_cpr_coef_reg[i],
2431			       regval[i]);
2432}
2433
2434static void dispc_k2g_vp_set_ctm(struct dispc_device *dispc, u32 hw_videoport,
2435				 struct drm_color_ctm *ctm)
2436{
2437	u32 cprenable = 0;
2438
2439	if (ctm) {
2440		struct dispc_csc_coef cpr;
2441
2442		dispc_k2g_cpr_from_ctm(ctm, &cpr);
2443		dispc_k2g_vp_write_csc(dispc, hw_videoport, &cpr);
2444		cprenable = 1;
2445	}
2446
2447	VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONFIG,
2448		       cprenable, 15, 15);
2449}
2450
2451static s16 dispc_S31_32_to_s3_8(s64 coef)
2452{
2453	u64 sign_bit = 1ULL << 63;
2454	u64 cbits = (u64)coef;
2455	s16 ret;
2456
2457	if (cbits & sign_bit)
2458		ret = -clamp_val(((cbits & ~sign_bit) >> 24), 0, 0x400);
2459	else
2460		ret = clamp_val(((cbits & ~sign_bit) >> 24), 0, 0x3FF);
2461
2462	return ret;
2463}
2464
2465static void dispc_csc_from_ctm(const struct drm_color_ctm *ctm,
2466			       struct dispc_csc_coef *cpr)
2467{
2468	memset(cpr, 0, sizeof(*cpr));
2469
2470	cpr->to_regval = dispc_csc_cpr_regval;
2471	cpr->m[CSC_RR] = dispc_S31_32_to_s3_8(ctm->matrix[0]);
2472	cpr->m[CSC_RG] = dispc_S31_32_to_s3_8(ctm->matrix[1]);
2473	cpr->m[CSC_RB] = dispc_S31_32_to_s3_8(ctm->matrix[2]);
2474	cpr->m[CSC_GR] = dispc_S31_32_to_s3_8(ctm->matrix[3]);
2475	cpr->m[CSC_GG] = dispc_S31_32_to_s3_8(ctm->matrix[4]);
2476	cpr->m[CSC_GB] = dispc_S31_32_to_s3_8(ctm->matrix[5]);
2477	cpr->m[CSC_BR] = dispc_S31_32_to_s3_8(ctm->matrix[6]);
2478	cpr->m[CSC_BG] = dispc_S31_32_to_s3_8(ctm->matrix[7]);
2479	cpr->m[CSC_BB] = dispc_S31_32_to_s3_8(ctm->matrix[8]);
2480}
2481
2482static void dispc_k3_vp_write_csc(struct dispc_device *dispc, u32 hw_videoport,
2483				  const struct dispc_csc_coef *csc)
2484{
2485	static const u16 dispc_vp_csc_coef_reg[DISPC_CSC_REGVAL_LEN] = {
2486		DISPC_VP_CSC_COEF0, DISPC_VP_CSC_COEF1, DISPC_VP_CSC_COEF2,
2487		DISPC_VP_CSC_COEF3, DISPC_VP_CSC_COEF4, DISPC_VP_CSC_COEF5,
2488		DISPC_VP_CSC_COEF6, DISPC_VP_CSC_COEF7,
2489	};
2490	u32 regval[DISPC_CSC_REGVAL_LEN];
2491	unsigned int i;
2492
2493	csc->to_regval(csc, regval);
2494
2495	for (i = 0; i < ARRAY_SIZE(regval); i++)
2496		dispc_vp_write(dispc, hw_videoport, dispc_vp_csc_coef_reg[i],
2497			       regval[i]);
2498}
2499
2500static void dispc_k3_vp_set_ctm(struct dispc_device *dispc, u32 hw_videoport,
2501				struct drm_color_ctm *ctm)
2502{
2503	u32 colorconvenable = 0;
2504
2505	if (ctm) {
2506		struct dispc_csc_coef csc;
2507
2508		dispc_csc_from_ctm(ctm, &csc);
2509		dispc_k3_vp_write_csc(dispc, hw_videoport, &csc);
2510		colorconvenable = 1;
2511	}
2512
2513	VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONFIG,
2514		       colorconvenable, 24, 24);
2515}
2516
2517static void dispc_vp_set_color_mgmt(struct dispc_device *dispc,
2518				    u32 hw_videoport,
2519				    const struct drm_crtc_state *state,
2520				    bool newmodeset)
2521{
2522	struct drm_color_lut *lut = NULL;
2523	struct drm_color_ctm *ctm = NULL;
2524	unsigned int length = 0;
2525
2526	if (!(state->color_mgmt_changed || newmodeset))
2527		return;
2528
2529	if (state->gamma_lut) {
2530		lut = (struct drm_color_lut *)state->gamma_lut->data;
2531		length = state->gamma_lut->length / sizeof(*lut);
2532	}
2533
2534	dispc_vp_set_gamma(dispc, hw_videoport, lut, length);
2535
2536	if (state->ctm)
2537		ctm = (struct drm_color_ctm *)state->ctm->data;
2538
2539	if (dispc->feat->subrev == DISPC_K2G)
2540		dispc_k2g_vp_set_ctm(dispc, hw_videoport, ctm);
2541	else
2542		dispc_k3_vp_set_ctm(dispc, hw_videoport, ctm);
2543}
2544
2545void dispc_vp_setup(struct dispc_device *dispc, u32 hw_videoport,
2546		    const struct drm_crtc_state *state, bool newmodeset)
2547{
2548	dispc_vp_set_default_color(dispc, hw_videoport, 0);
2549	dispc_vp_set_color_mgmt(dispc, hw_videoport, state, newmodeset);
2550}
2551
2552int dispc_runtime_suspend(struct dispc_device *dispc)
2553{
2554	dev_dbg(dispc->dev, "suspend\n");
2555
2556	dispc->is_enabled = false;
2557
2558	clk_disable_unprepare(dispc->fclk);
2559
2560	return 0;
2561}
2562
2563int dispc_runtime_resume(struct dispc_device *dispc)
2564{
2565	dev_dbg(dispc->dev, "resume\n");
2566
2567	clk_prepare_enable(dispc->fclk);
2568
2569	if (REG_GET(dispc, DSS_SYSSTATUS, 0, 0) == 0)
2570		dev_warn(dispc->dev, "DSS FUNC RESET not done!\n");
2571
2572	dev_dbg(dispc->dev, "OMAP DSS7 rev 0x%x\n",
2573		dispc_read(dispc, DSS_REVISION));
2574
2575	dev_dbg(dispc->dev, "VP RESETDONE %d,%d,%d\n",
2576		REG_GET(dispc, DSS_SYSSTATUS, 1, 1),
2577		REG_GET(dispc, DSS_SYSSTATUS, 2, 2),
2578		REG_GET(dispc, DSS_SYSSTATUS, 3, 3));
2579
2580	if (dispc->feat->subrev == DISPC_AM65X)
2581		dev_dbg(dispc->dev, "OLDI RESETDONE %d,%d,%d\n",
2582			REG_GET(dispc, DSS_SYSSTATUS, 5, 5),
2583			REG_GET(dispc, DSS_SYSSTATUS, 6, 6),
2584			REG_GET(dispc, DSS_SYSSTATUS, 7, 7));
2585
2586	dev_dbg(dispc->dev, "DISPC IDLE %d\n",
2587		REG_GET(dispc, DSS_SYSSTATUS, 9, 9));
2588
2589	dispc_initial_config(dispc);
2590
2591	dispc->is_enabled = true;
2592
2593	tidss_irq_resume(dispc->tidss);
2594
2595	return 0;
2596}
2597
2598void dispc_remove(struct tidss_device *tidss)
2599{
2600	dev_dbg(tidss->dev, "%s\n", __func__);
2601
2602	tidss->dispc = NULL;
2603}
2604
2605static int dispc_iomap_resource(struct platform_device *pdev, const char *name,
2606				void __iomem **base)
2607{
2608	struct resource *res;
2609	void __iomem *b;
2610
2611	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
2612	if (!res) {
2613		dev_err(&pdev->dev, "cannot get mem resource '%s'\n", name);
2614		return -EINVAL;
2615	}
2616
2617	b = devm_ioremap_resource(&pdev->dev, res);
2618	if (IS_ERR(b)) {
2619		dev_err(&pdev->dev, "cannot ioremap resource '%s'\n", name);
2620		return PTR_ERR(b);
2621	}
2622
2623	*base = b;
2624
2625	return 0;
2626}
2627
2628static int dispc_init_am65x_oldi_io_ctrl(struct device *dev,
2629					 struct dispc_device *dispc)
2630{
2631	dispc->oldi_io_ctrl =
2632		syscon_regmap_lookup_by_phandle(dev->of_node,
2633						"ti,am65x-oldi-io-ctrl");
2634	if (PTR_ERR(dispc->oldi_io_ctrl) == -ENODEV) {
2635		dispc->oldi_io_ctrl = NULL;
2636	} else if (IS_ERR(dispc->oldi_io_ctrl)) {
2637		dev_err(dev, "%s: syscon_regmap_lookup_by_phandle failed %ld\n",
2638			__func__, PTR_ERR(dispc->oldi_io_ctrl));
2639		return PTR_ERR(dispc->oldi_io_ctrl);
2640	}
2641	return 0;
2642}
2643
2644int dispc_init(struct tidss_device *tidss)
2645{
2646	struct device *dev = tidss->dev;
2647	struct platform_device *pdev = to_platform_device(dev);
2648	struct dispc_device *dispc;
2649	const struct dispc_features *feat;
2650	unsigned int i, num_fourccs;
2651	int r = 0;
2652
2653	dev_dbg(dev, "%s\n", __func__);
2654
2655	feat = tidss->feat;
2656
2657	if (feat->subrev != DISPC_K2G) {
2658		r = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
2659		if (r)
2660			dev_warn(dev, "cannot set DMA masks to 48-bit\n");
2661	}
2662
2663	dispc = devm_kzalloc(dev, sizeof(*dispc), GFP_KERNEL);
2664	if (!dispc)
2665		return -ENOMEM;
2666
2667	dispc->fourccs = devm_kcalloc(dev, ARRAY_SIZE(dispc_color_formats),
2668				      sizeof(*dispc->fourccs), GFP_KERNEL);
2669	if (!dispc->fourccs)
2670		return -ENOMEM;
2671
2672	num_fourccs = 0;
2673	for (i = 0; i < ARRAY_SIZE(dispc_color_formats); ++i)
2674		dispc->fourccs[num_fourccs++] = dispc_color_formats[i].fourcc;
2675
2676	dispc->num_fourccs = num_fourccs;
2677	dispc->tidss = tidss;
2678	dispc->dev = dev;
2679	dispc->feat = feat;
2680
2681	dispc_common_regmap = dispc->feat->common_regs;
2682
2683	r = dispc_iomap_resource(pdev, dispc->feat->common,
2684				 &dispc->base_common);
2685	if (r)
2686		return r;
2687
2688	for (i = 0; i < dispc->feat->num_planes; i++) {
2689		r = dispc_iomap_resource(pdev, dispc->feat->vid_name[i],
2690					 &dispc->base_vid[i]);
2691		if (r)
2692			return r;
2693	}
2694
2695	for (i = 0; i < dispc->feat->num_vps; i++) {
2696		u32 gamma_size = dispc->feat->vp_feat.color.gamma_size;
2697		u32 *gamma_table;
2698		struct clk *clk;
2699
2700		r = dispc_iomap_resource(pdev, dispc->feat->ovr_name[i],
2701					 &dispc->base_ovr[i]);
2702		if (r)
2703			return r;
2704
2705		r = dispc_iomap_resource(pdev, dispc->feat->vp_name[i],
2706					 &dispc->base_vp[i]);
2707		if (r)
2708			return r;
2709
2710		clk = devm_clk_get(dev, dispc->feat->vpclk_name[i]);
2711		if (IS_ERR(clk)) {
2712			dev_err(dev, "%s: Failed to get clk %s:%ld\n", __func__,
2713				dispc->feat->vpclk_name[i], PTR_ERR(clk));
2714			return PTR_ERR(clk);
2715		}
2716		dispc->vp_clk[i] = clk;
2717
2718		gamma_table = devm_kmalloc_array(dev, gamma_size,
2719						 sizeof(*gamma_table),
2720						 GFP_KERNEL);
2721		if (!gamma_table)
2722			return -ENOMEM;
2723		dispc->vp_data[i].gamma_table = gamma_table;
2724	}
2725
2726	if (feat->subrev == DISPC_AM65X) {
2727		r = dispc_init_am65x_oldi_io_ctrl(dev, dispc);
2728		if (r)
2729			return r;
2730	}
2731
2732	dispc->fclk = devm_clk_get(dev, "fck");
2733	if (IS_ERR(dispc->fclk)) {
2734		dev_err(dev, "%s: Failed to get fclk: %ld\n",
2735			__func__, PTR_ERR(dispc->fclk));
2736		return PTR_ERR(dispc->fclk);
2737	}
2738	dev_dbg(dev, "DSS fclk %lu Hz\n", clk_get_rate(dispc->fclk));
2739
2740	of_property_read_u32(dispc->dev->of_node, "max-memory-bandwidth",
2741			     &dispc->memory_bandwidth_limit);
2742
2743	tidss->dispc = dispc;
2744
2745	return 0;
2746}