Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright 2019 NXP.
  4 */
  5
  6#include <linux/device.h>
  7#include <linux/slab.h>
  8
  9#include "dcss-dev.h"
 10
 11#define DCSS_SS_SYS_CTRL			0x00
 12#define   RUN_EN				BIT(0)
 13#define DCSS_SS_DISPLAY				0x10
 14#define   LRC_X_POS				0
 15#define   LRC_X_MASK				GENMASK(12, 0)
 16#define   LRC_Y_POS				16
 17#define   LRC_Y_MASK				GENMASK(28, 16)
 18#define DCSS_SS_HSYNC				0x20
 19#define DCSS_SS_VSYNC				0x30
 20#define   SYNC_START_POS			0
 21#define   SYNC_START_MASK			GENMASK(12, 0)
 22#define   SYNC_END_POS				16
 23#define   SYNC_END_MASK				GENMASK(28, 16)
 24#define   SYNC_POL				BIT(31)
 25#define DCSS_SS_DE_ULC				0x40
 26#define   ULC_X_POS				0
 27#define   ULC_X_MASK				GENMASK(12, 0)
 28#define   ULC_Y_POS				16
 29#define   ULC_Y_MASK				GENMASK(28, 16)
 30#define   ULC_POL				BIT(31)
 31#define DCSS_SS_DE_LRC				0x50
 32#define DCSS_SS_MODE				0x60
 33#define   PIPE_MODE_POS				0
 34#define   PIPE_MODE_MASK			GENMASK(1, 0)
 35#define DCSS_SS_COEFF				0x70
 36#define   HORIZ_A_POS				0
 37#define   HORIZ_A_MASK				GENMASK(3, 0)
 38#define   HORIZ_B_POS				4
 39#define   HORIZ_B_MASK				GENMASK(7, 4)
 40#define   HORIZ_C_POS				8
 41#define   HORIZ_C_MASK				GENMASK(11, 8)
 42#define   HORIZ_H_NORM_POS			12
 43#define   HORIZ_H_NORM_MASK			GENMASK(14, 12)
 44#define   VERT_A_POS				16
 45#define   VERT_A_MASK				GENMASK(19, 16)
 46#define   VERT_B_POS				20
 47#define   VERT_B_MASK				GENMASK(23, 20)
 48#define   VERT_C_POS				24
 49#define   VERT_C_MASK				GENMASK(27, 24)
 50#define   VERT_H_NORM_POS			28
 51#define   VERT_H_NORM_MASK			GENMASK(30, 28)
 52#define DCSS_SS_CLIP_CB				0x80
 53#define DCSS_SS_CLIP_CR				0x90
 54#define   CLIP_MIN_POS				0
 55#define   CLIP_MIN_MASK				GENMASK(9, 0)
 56#define   CLIP_MAX_POS				0
 57#define   CLIP_MAX_MASK				GENMASK(23, 16)
 58#define DCSS_SS_INTER_MODE			0xA0
 59#define   INT_EN				BIT(0)
 60#define   VSYNC_SHIFT				BIT(1)
 61
 62struct dcss_ss {
 63	struct device *dev;
 64	void __iomem *base_reg;
 65	u32 base_ofs;
 66
 67	struct dcss_ctxld *ctxld;
 68	u32 ctx_id;
 69
 70	bool in_use;
 71};
 72
 73static void dcss_ss_write(struct dcss_ss *ss, u32 val, u32 ofs)
 74{
 75	if (!ss->in_use)
 76		dcss_writel(val, ss->base_reg + ofs);
 77
 78	dcss_ctxld_write(ss->ctxld, ss->ctx_id, val,
 79			 ss->base_ofs + ofs);
 80}
 81
 82int dcss_ss_init(struct dcss_dev *dcss, unsigned long ss_base)
 83{
 84	struct dcss_ss *ss;
 85
 86	ss = kzalloc(sizeof(*ss), GFP_KERNEL);
 87	if (!ss)
 88		return -ENOMEM;
 89
 90	dcss->ss = ss;
 91	ss->dev = dcss->dev;
 92	ss->ctxld = dcss->ctxld;
 93
 94	ss->base_reg = ioremap(ss_base, SZ_4K);
 95	if (!ss->base_reg) {
 96		dev_err(dcss->dev, "ss: unable to remap ss base\n");
 97		kfree(ss);
 98		return -ENOMEM;
 99	}
100
101	ss->base_ofs = ss_base;
102	ss->ctx_id = CTX_SB_HP;
103
104	return 0;
105}
106
107void dcss_ss_exit(struct dcss_ss *ss)
108{
109	/* stop SS */
110	dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL);
111
112	if (ss->base_reg)
113		iounmap(ss->base_reg);
114
115	kfree(ss);
116}
117
118void dcss_ss_subsam_set(struct dcss_ss *ss)
119{
120	dcss_ss_write(ss, 0x41614161, DCSS_SS_COEFF);
121	dcss_ss_write(ss, 0, DCSS_SS_MODE);
122	dcss_ss_write(ss, 0x03ff0000, DCSS_SS_CLIP_CB);
123	dcss_ss_write(ss, 0x03ff0000, DCSS_SS_CLIP_CR);
124}
125
126void dcss_ss_sync_set(struct dcss_ss *ss, struct videomode *vm,
127		      bool phsync, bool pvsync)
128{
129	u16 lrc_x, lrc_y;
130	u16 hsync_start, hsync_end;
131	u16 vsync_start, vsync_end;
132	u16 de_ulc_x, de_ulc_y;
133	u16 de_lrc_x, de_lrc_y;
134
135	lrc_x = vm->hfront_porch + vm->hback_porch + vm->hsync_len +
136		vm->hactive - 1;
137	lrc_y = vm->vfront_porch + vm->vback_porch + vm->vsync_len +
138		vm->vactive - 1;
139
140	dcss_ss_write(ss, (lrc_y << LRC_Y_POS) | lrc_x, DCSS_SS_DISPLAY);
141
142	hsync_start = vm->hfront_porch + vm->hback_porch + vm->hsync_len +
143		      vm->hactive - 1;
144	hsync_end = vm->hsync_len - 1;
145
146	dcss_ss_write(ss, (phsync ? SYNC_POL : 0) |
147		      ((u32)hsync_end << SYNC_END_POS) | hsync_start,
148		      DCSS_SS_HSYNC);
149
150	vsync_start = vm->vfront_porch - 1;
151	vsync_end = vm->vfront_porch + vm->vsync_len - 1;
152
153	dcss_ss_write(ss, (pvsync ? SYNC_POL : 0) |
154		      ((u32)vsync_end << SYNC_END_POS) | vsync_start,
155		      DCSS_SS_VSYNC);
156
157	de_ulc_x = vm->hsync_len + vm->hback_porch - 1;
158	de_ulc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch;
159
160	dcss_ss_write(ss, SYNC_POL | ((u32)de_ulc_y << ULC_Y_POS) | de_ulc_x,
161		      DCSS_SS_DE_ULC);
162
163	de_lrc_x = vm->hsync_len + vm->hback_porch + vm->hactive - 1;
164	de_lrc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch +
165		   vm->vactive - 1;
166
167	dcss_ss_write(ss, (de_lrc_y << LRC_Y_POS) | de_lrc_x, DCSS_SS_DE_LRC);
168}
169
170void dcss_ss_enable(struct dcss_ss *ss)
171{
172	dcss_ss_write(ss, RUN_EN, DCSS_SS_SYS_CTRL);
173	ss->in_use = true;
174}
175
176void dcss_ss_shutoff(struct dcss_ss *ss)
177{
178	dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL);
179	ss->in_use = false;
180}