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