1 // SPDX-License-Identifier: GPL-2.0
6 #include <linux/device.h>
7 #include <linux/slab.h>
11 #define DCSS_SS_SYS_CTRL 0x00
13 #define DCSS_SS_DISPLAY 0x10
15 #define LRC_X_MASK GENMASK(12, 0)
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
27 #define ULC_X_MASK GENMASK(12, 0)
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
37 #define HORIZ_A_MASK GENMASK(3, 0)
39 #define HORIZ_B_MASK GENMASK(7, 4)
41 #define HORIZ_C_MASK GENMASK(11, 8)
42 #define HORIZ_H_NORM_POS 12
43 #define HORIZ_H_NORM_MASK GENMASK(14, 12)
45 #define VERT_A_MASK GENMASK(19, 16)
47 #define VERT_B_MASK GENMASK(23, 20)
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
60 #define VSYNC_SHIFT BIT(1)
64 void __iomem *base_reg;
67 struct dcss_ctxld *ctxld;
73 static void dcss_ss_write(struct dcss_ss *ss, u32 val, u32 ofs)
76 dcss_writel(val, ss->base_reg + ofs);
78 dcss_ctxld_write(ss->ctxld, ss->ctx_id, val,
82 int dcss_ss_init(struct dcss_dev *dcss, unsigned long ss_base)
86 ss = devm_kzalloc(dcss->dev, sizeof(*ss), GFP_KERNEL);
92 ss->ctxld = dcss->ctxld;
94 ss->base_reg = devm_ioremap(ss->dev, ss_base, SZ_4K);
96 dev_err(ss->dev, "ss: unable to remap ss base\n");
100 ss->base_ofs = ss_base;
101 ss->ctx_id = CTX_SB_HP;
106 void dcss_ss_exit(struct dcss_ss *ss)
109 dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL);
112 void dcss_ss_subsam_set(struct dcss_ss *ss)
114 dcss_ss_write(ss, 0x41614161, DCSS_SS_COEFF);
115 dcss_ss_write(ss, 0, DCSS_SS_MODE);
116 dcss_ss_write(ss, 0x03ff0000, DCSS_SS_CLIP_CB);
117 dcss_ss_write(ss, 0x03ff0000, DCSS_SS_CLIP_CR);
120 void dcss_ss_sync_set(struct dcss_ss *ss, struct videomode *vm,
121 bool phsync, bool pvsync)
124 u16 hsync_start, hsync_end;
125 u16 vsync_start, vsync_end;
126 u16 de_ulc_x, de_ulc_y;
127 u16 de_lrc_x, de_lrc_y;
129 lrc_x = vm->hfront_porch + vm->hback_porch + vm->hsync_len +
131 lrc_y = vm->vfront_porch + vm->vback_porch + vm->vsync_len +
134 dcss_ss_write(ss, (lrc_y << LRC_Y_POS) | lrc_x, DCSS_SS_DISPLAY);
136 hsync_start = vm->hfront_porch + vm->hback_porch + vm->hsync_len +
138 hsync_end = vm->hsync_len - 1;
140 dcss_ss_write(ss, (phsync ? SYNC_POL : 0) |
141 ((u32)hsync_end << SYNC_END_POS) | hsync_start,
144 vsync_start = vm->vfront_porch - 1;
145 vsync_end = vm->vfront_porch + vm->vsync_len - 1;
147 dcss_ss_write(ss, (pvsync ? SYNC_POL : 0) |
148 ((u32)vsync_end << SYNC_END_POS) | vsync_start,
151 de_ulc_x = vm->hsync_len + vm->hback_porch - 1;
152 de_ulc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch;
154 dcss_ss_write(ss, SYNC_POL | ((u32)de_ulc_y << ULC_Y_POS) | de_ulc_x,
157 de_lrc_x = vm->hsync_len + vm->hback_porch + vm->hactive - 1;
158 de_lrc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch +
161 dcss_ss_write(ss, (de_lrc_y << LRC_Y_POS) | de_lrc_x, DCSS_SS_DE_LRC);
164 void dcss_ss_enable(struct dcss_ss *ss)
166 dcss_ss_write(ss, RUN_EN, DCSS_SS_SYS_CTRL);
170 void dcss_ss_shutoff(struct dcss_ss *ss)
172 dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL);