cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tidss_dispc.c (72647B)


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