Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright 2019 NXP.
0004  */
0005 
0006 #include <linux/device.h>
0007 #include <linux/slab.h>
0008 
0009 #include "dcss-dev.h"
0010 
0011 #define DCSS_SS_SYS_CTRL            0x00
0012 #define   RUN_EN                BIT(0)
0013 #define DCSS_SS_DISPLAY             0x10
0014 #define   LRC_X_POS             0
0015 #define   LRC_X_MASK                GENMASK(12, 0)
0016 #define   LRC_Y_POS             16
0017 #define   LRC_Y_MASK                GENMASK(28, 16)
0018 #define DCSS_SS_HSYNC               0x20
0019 #define DCSS_SS_VSYNC               0x30
0020 #define   SYNC_START_POS            0
0021 #define   SYNC_START_MASK           GENMASK(12, 0)
0022 #define   SYNC_END_POS              16
0023 #define   SYNC_END_MASK             GENMASK(28, 16)
0024 #define   SYNC_POL              BIT(31)
0025 #define DCSS_SS_DE_ULC              0x40
0026 #define   ULC_X_POS             0
0027 #define   ULC_X_MASK                GENMASK(12, 0)
0028 #define   ULC_Y_POS             16
0029 #define   ULC_Y_MASK                GENMASK(28, 16)
0030 #define   ULC_POL               BIT(31)
0031 #define DCSS_SS_DE_LRC              0x50
0032 #define DCSS_SS_MODE                0x60
0033 #define   PIPE_MODE_POS             0
0034 #define   PIPE_MODE_MASK            GENMASK(1, 0)
0035 #define DCSS_SS_COEFF               0x70
0036 #define   HORIZ_A_POS               0
0037 #define   HORIZ_A_MASK              GENMASK(3, 0)
0038 #define   HORIZ_B_POS               4
0039 #define   HORIZ_B_MASK              GENMASK(7, 4)
0040 #define   HORIZ_C_POS               8
0041 #define   HORIZ_C_MASK              GENMASK(11, 8)
0042 #define   HORIZ_H_NORM_POS          12
0043 #define   HORIZ_H_NORM_MASK         GENMASK(14, 12)
0044 #define   VERT_A_POS                16
0045 #define   VERT_A_MASK               GENMASK(19, 16)
0046 #define   VERT_B_POS                20
0047 #define   VERT_B_MASK               GENMASK(23, 20)
0048 #define   VERT_C_POS                24
0049 #define   VERT_C_MASK               GENMASK(27, 24)
0050 #define   VERT_H_NORM_POS           28
0051 #define   VERT_H_NORM_MASK          GENMASK(30, 28)
0052 #define DCSS_SS_CLIP_CB             0x80
0053 #define DCSS_SS_CLIP_CR             0x90
0054 #define   CLIP_MIN_POS              0
0055 #define   CLIP_MIN_MASK             GENMASK(9, 0)
0056 #define   CLIP_MAX_POS              0
0057 #define   CLIP_MAX_MASK             GENMASK(23, 16)
0058 #define DCSS_SS_INTER_MODE          0xA0
0059 #define   INT_EN                BIT(0)
0060 #define   VSYNC_SHIFT               BIT(1)
0061 
0062 struct dcss_ss {
0063     struct device *dev;
0064     void __iomem *base_reg;
0065     u32 base_ofs;
0066 
0067     struct dcss_ctxld *ctxld;
0068     u32 ctx_id;
0069 
0070     bool in_use;
0071 };
0072 
0073 static void dcss_ss_write(struct dcss_ss *ss, u32 val, u32 ofs)
0074 {
0075     if (!ss->in_use)
0076         dcss_writel(val, ss->base_reg + ofs);
0077 
0078     dcss_ctxld_write(ss->ctxld, ss->ctx_id, val,
0079              ss->base_ofs + ofs);
0080 }
0081 
0082 int dcss_ss_init(struct dcss_dev *dcss, unsigned long ss_base)
0083 {
0084     struct dcss_ss *ss;
0085 
0086     ss = kzalloc(sizeof(*ss), GFP_KERNEL);
0087     if (!ss)
0088         return -ENOMEM;
0089 
0090     dcss->ss = ss;
0091     ss->dev = dcss->dev;
0092     ss->ctxld = dcss->ctxld;
0093 
0094     ss->base_reg = ioremap(ss_base, SZ_4K);
0095     if (!ss->base_reg) {
0096         dev_err(dcss->dev, "ss: unable to remap ss base\n");
0097         kfree(ss);
0098         return -ENOMEM;
0099     }
0100 
0101     ss->base_ofs = ss_base;
0102     ss->ctx_id = CTX_SB_HP;
0103 
0104     return 0;
0105 }
0106 
0107 void dcss_ss_exit(struct dcss_ss *ss)
0108 {
0109     /* stop SS */
0110     dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL);
0111 
0112     if (ss->base_reg)
0113         iounmap(ss->base_reg);
0114 
0115     kfree(ss);
0116 }
0117 
0118 void dcss_ss_subsam_set(struct dcss_ss *ss)
0119 {
0120     dcss_ss_write(ss, 0x41614161, DCSS_SS_COEFF);
0121     dcss_ss_write(ss, 0, DCSS_SS_MODE);
0122     dcss_ss_write(ss, 0x03ff0000, DCSS_SS_CLIP_CB);
0123     dcss_ss_write(ss, 0x03ff0000, DCSS_SS_CLIP_CR);
0124 }
0125 
0126 void dcss_ss_sync_set(struct dcss_ss *ss, struct videomode *vm,
0127               bool phsync, bool pvsync)
0128 {
0129     u16 lrc_x, lrc_y;
0130     u16 hsync_start, hsync_end;
0131     u16 vsync_start, vsync_end;
0132     u16 de_ulc_x, de_ulc_y;
0133     u16 de_lrc_x, de_lrc_y;
0134 
0135     lrc_x = vm->hfront_porch + vm->hback_porch + vm->hsync_len +
0136         vm->hactive - 1;
0137     lrc_y = vm->vfront_porch + vm->vback_porch + vm->vsync_len +
0138         vm->vactive - 1;
0139 
0140     dcss_ss_write(ss, (lrc_y << LRC_Y_POS) | lrc_x, DCSS_SS_DISPLAY);
0141 
0142     hsync_start = vm->hfront_porch + vm->hback_porch + vm->hsync_len +
0143               vm->hactive - 1;
0144     hsync_end = vm->hsync_len - 1;
0145 
0146     dcss_ss_write(ss, (phsync ? SYNC_POL : 0) |
0147               ((u32)hsync_end << SYNC_END_POS) | hsync_start,
0148               DCSS_SS_HSYNC);
0149 
0150     vsync_start = vm->vfront_porch - 1;
0151     vsync_end = vm->vfront_porch + vm->vsync_len - 1;
0152 
0153     dcss_ss_write(ss, (pvsync ? SYNC_POL : 0) |
0154               ((u32)vsync_end << SYNC_END_POS) | vsync_start,
0155               DCSS_SS_VSYNC);
0156 
0157     de_ulc_x = vm->hsync_len + vm->hback_porch - 1;
0158     de_ulc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch;
0159 
0160     dcss_ss_write(ss, SYNC_POL | ((u32)de_ulc_y << ULC_Y_POS) | de_ulc_x,
0161               DCSS_SS_DE_ULC);
0162 
0163     de_lrc_x = vm->hsync_len + vm->hback_porch + vm->hactive - 1;
0164     de_lrc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch +
0165            vm->vactive - 1;
0166 
0167     dcss_ss_write(ss, (de_lrc_y << LRC_Y_POS) | de_lrc_x, DCSS_SS_DE_LRC);
0168 }
0169 
0170 void dcss_ss_enable(struct dcss_ss *ss)
0171 {
0172     dcss_ss_write(ss, RUN_EN, DCSS_SS_SYS_CTRL);
0173     ss->in_use = true;
0174 }
0175 
0176 void dcss_ss_shutoff(struct dcss_ss *ss)
0177 {
0178     dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL);
0179     ss->in_use = false;
0180 }