175 lines · c
1// SPDX-License-Identifier: GPL-2.02/*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 0x0012#define RUN_EN BIT(0)13#define DCSS_SS_DISPLAY 0x1014#define LRC_X_POS 015#define LRC_X_MASK GENMASK(12, 0)16#define LRC_Y_POS 1617#define LRC_Y_MASK GENMASK(28, 16)18#define DCSS_SS_HSYNC 0x2019#define DCSS_SS_VSYNC 0x3020#define SYNC_START_POS 021#define SYNC_START_MASK GENMASK(12, 0)22#define SYNC_END_POS 1623#define SYNC_END_MASK GENMASK(28, 16)24#define SYNC_POL BIT(31)25#define DCSS_SS_DE_ULC 0x4026#define ULC_X_POS 027#define ULC_X_MASK GENMASK(12, 0)28#define ULC_Y_POS 1629#define ULC_Y_MASK GENMASK(28, 16)30#define ULC_POL BIT(31)31#define DCSS_SS_DE_LRC 0x5032#define DCSS_SS_MODE 0x6033#define PIPE_MODE_POS 034#define PIPE_MODE_MASK GENMASK(1, 0)35#define DCSS_SS_COEFF 0x7036#define HORIZ_A_POS 037#define HORIZ_A_MASK GENMASK(3, 0)38#define HORIZ_B_POS 439#define HORIZ_B_MASK GENMASK(7, 4)40#define HORIZ_C_POS 841#define HORIZ_C_MASK GENMASK(11, 8)42#define HORIZ_H_NORM_POS 1243#define HORIZ_H_NORM_MASK GENMASK(14, 12)44#define VERT_A_POS 1645#define VERT_A_MASK GENMASK(19, 16)46#define VERT_B_POS 2047#define VERT_B_MASK GENMASK(23, 20)48#define VERT_C_POS 2449#define VERT_C_MASK GENMASK(27, 24)50#define VERT_H_NORM_POS 2851#define VERT_H_NORM_MASK GENMASK(30, 28)52#define DCSS_SS_CLIP_CB 0x8053#define DCSS_SS_CLIP_CR 0x9054#define CLIP_MIN_POS 055#define CLIP_MIN_MASK GENMASK(9, 0)56#define CLIP_MAX_POS 057#define CLIP_MAX_MASK GENMASK(23, 16)58#define DCSS_SS_INTER_MODE 0xA059#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 = devm_kzalloc(dcss->dev, 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 = devm_ioremap(ss->dev, ss_base, SZ_4K);95 if (!ss->base_reg) {96 dev_err(ss->dev, "ss: unable to remap ss base\n");97 return -ENOMEM;98 }99 100 ss->base_ofs = ss_base;101 ss->ctx_id = CTX_SB_HP;102 103 return 0;104}105 106void dcss_ss_exit(struct dcss_ss *ss)107{108 /* stop SS */109 dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL);110}111 112void dcss_ss_subsam_set(struct dcss_ss *ss)113{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);118}119 120void dcss_ss_sync_set(struct dcss_ss *ss, struct videomode *vm,121 bool phsync, bool pvsync)122{123 u16 lrc_x, lrc_y;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;128 129 lrc_x = vm->hfront_porch + vm->hback_porch + vm->hsync_len +130 vm->hactive - 1;131 lrc_y = vm->vfront_porch + vm->vback_porch + vm->vsync_len +132 vm->vactive - 1;133 134 dcss_ss_write(ss, (lrc_y << LRC_Y_POS) | lrc_x, DCSS_SS_DISPLAY);135 136 hsync_start = vm->hfront_porch + vm->hback_porch + vm->hsync_len +137 vm->hactive - 1;138 hsync_end = vm->hsync_len - 1;139 140 dcss_ss_write(ss, (phsync ? SYNC_POL : 0) |141 ((u32)hsync_end << SYNC_END_POS) | hsync_start,142 DCSS_SS_HSYNC);143 144 vsync_start = vm->vfront_porch - 1;145 vsync_end = vm->vfront_porch + vm->vsync_len - 1;146 147 dcss_ss_write(ss, (pvsync ? SYNC_POL : 0) |148 ((u32)vsync_end << SYNC_END_POS) | vsync_start,149 DCSS_SS_VSYNC);150 151 de_ulc_x = vm->hsync_len + vm->hback_porch - 1;152 de_ulc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch;153 154 dcss_ss_write(ss, SYNC_POL | ((u32)de_ulc_y << ULC_Y_POS) | de_ulc_x,155 DCSS_SS_DE_ULC);156 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 +159 vm->vactive - 1;160 161 dcss_ss_write(ss, (de_lrc_y << LRC_Y_POS) | de_lrc_x, DCSS_SS_DE_LRC);162}163 164void dcss_ss_enable(struct dcss_ss *ss)165{166 dcss_ss_write(ss, RUN_EN, DCSS_SS_SYS_CTRL);167 ss->in_use = true;168}169 170void dcss_ss_shutoff(struct dcss_ss *ss)171{172 dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL);173 ss->in_use = false;174}175