1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
/*
* Copyright (C) 2017 NXP
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <linux/device.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <video/imx-dcss.h>
#include "dcss-prv.h"
#define USE_CTXLD
#define DCSS_RDSRC_CTRL_STATUS 0x00
#define RDSRC_RD_ERR BIT(31)
#define RDSRC_FRAME_COMP BIT(30)
#define RDSRC_FIFO_SIZE_POS 16
#define RDSRC_FIFO_SIZE_MASK GENMASK(22, 16)
#define RDSRC_RD_ERR_EN BIT(15)
#define RDSRC_FRAME_COMP_EN BIT(14)
#define RDSRC_P_SIZE_POS 7
#define RDSRC_P_SIZE_MASK GENMASK(9, 7)
#define RDSRC_T_SIZE_POS 5
#define RDSRC_T_SIZE_MASK GENMASK(6, 5)
#define RDSRC_BPP_POS 2
#define RDSRC_BPP_MASK GENMASK(4, 2)
#define RDSRC_ENABLE BIT(0)
#define DCSS_RDSRC_BASE_ADDR 0x10
#define DCSS_RDSRC_PITCH 0x14
#define DCSS_RDSRC_WIDTH 0x18
#define DCSS_RDSRC_HEIGHT 0x1C
struct dcss_rdsrc_priv {
void __iomem *base_reg;
u32 base_ofs;
struct dcss_soc *dcss;
u32 ctx_id;
u32 buf_addr;
u32 ctrl_status;
};
#ifdef CONFIG_DEBUG_FS
static struct dcss_debug_reg rdsrc_debug_reg[] = {
DCSS_DBG_REG(DCSS_RDSRC_CTRL_STATUS),
DCSS_DBG_REG(DCSS_RDSRC_BASE_ADDR),
DCSS_DBG_REG(DCSS_RDSRC_PITCH),
DCSS_DBG_REG(DCSS_RDSRC_WIDTH),
DCSS_DBG_REG(DCSS_RDSRC_HEIGHT),
};
void dcss_rdsrc_dump_regs(struct seq_file *s, void *data)
{
struct dcss_soc *dcss = data;
int i;
seq_puts(s, ">> Dumping RD_SRC:\n");
for (i = 0; i < ARRAY_SIZE(rdsrc_debug_reg); i++) {
seq_printf(s, "%-35s(0x%04x) -> 0x%08x\n",
rdsrc_debug_reg[i].name,
rdsrc_debug_reg[i].ofs,
dcss_readl(dcss->rdsrc_priv->base_reg +
rdsrc_debug_reg[i].ofs));
}
}
#endif
static void dcss_rdsrc_write(struct dcss_rdsrc_priv *rdsrc, u32 val, u32 ofs)
{
#if !defined(USE_CTXLD)
dcss_writel(val, rdsrc->base_reg + ofs);
#else
dcss_ctxld_write(rdsrc->dcss, rdsrc->ctx_id,
val, rdsrc->base_ofs + ofs);
#endif
}
int dcss_rdsrc_init(struct dcss_soc *dcss, unsigned long rdsrc_base)
{
struct dcss_rdsrc_priv *rdsrc;
rdsrc = devm_kzalloc(dcss->dev, sizeof(*rdsrc), GFP_KERNEL);
if (!rdsrc)
return -ENOMEM;
rdsrc->base_reg = devm_ioremap(dcss->dev, rdsrc_base, SZ_4K);
if (!rdsrc->base_reg) {
dev_err(dcss->dev, "rdsrc: unable to remap base\n");
return -ENOMEM;
}
dcss->rdsrc_priv = rdsrc;
rdsrc->base_ofs = rdsrc_base;
rdsrc->dcss = dcss;
#if defined(USE_CTXLD)
rdsrc->ctx_id = CTX_SB_HP;
#endif
return 0;
}
void dcss_rdsrc_exit(struct dcss_soc *dcss)
{
}
void dcss_rdsrc_setup(struct dcss_soc *dcss, u32 pix_format, u32 dst_xres,
u32 dst_yres, u32 base_addr)
{
struct dcss_rdsrc_priv *rdsrc = dcss->rdsrc_priv;
u32 buf_size, pitch, bpp;
/* since the scaler output is YUV444, the RDSRC output has to match */
bpp = 4;
rdsrc->ctrl_status = FIFO_512 << RDSRC_FIFO_SIZE_POS;
rdsrc->ctrl_status |= PSIZE_256 << RDSRC_P_SIZE_POS;
rdsrc->ctrl_status |= TSIZE_256 << RDSRC_T_SIZE_POS;
rdsrc->ctrl_status |= BPP_32_10BIT_OUTPUT << RDSRC_BPP_POS;
buf_size = dst_xres * dst_yres * bpp;
pitch = dst_xres * bpp;
rdsrc->buf_addr = base_addr;
dcss_rdsrc_write(rdsrc, rdsrc->buf_addr, DCSS_RDSRC_BASE_ADDR);
dcss_rdsrc_write(rdsrc, pitch, DCSS_RDSRC_PITCH);
dcss_rdsrc_write(rdsrc, dst_xres, DCSS_RDSRC_WIDTH);
dcss_rdsrc_write(rdsrc, dst_yres, DCSS_RDSRC_HEIGHT);
}
void dcss_rdsrc_enable(struct dcss_soc *dcss, bool en)
{
struct dcss_rdsrc_priv *rdsrc = dcss->rdsrc_priv;
/* RDSRC is turned off by setting the width and height to 0 */
if (!en) {
dcss_rdsrc_write(rdsrc, 0, DCSS_RDSRC_WIDTH);
dcss_rdsrc_write(rdsrc, 0, DCSS_RDSRC_HEIGHT);
}
dcss_rdsrc_write(rdsrc, rdsrc->ctrl_status, DCSS_RDSRC_CTRL_STATUS);
}
|