19ed785a9SBenjamin Gaignard // SPDX-License-Identifier: GPL-2.0
228ffeebbSFabien Dessenne /*
328ffeebbSFabien Dessenne * Copyright (C) STMicroelectronics SA 2014
428ffeebbSFabien Dessenne * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
528ffeebbSFabien Dessenne */
628ffeebbSFabien Dessenne
728ffeebbSFabien Dessenne #include <linux/delay.h>
828ffeebbSFabien Dessenne
928ffeebbSFabien Dessenne #include "bdisp.h"
1028ffeebbSFabien Dessenne #include "bdisp-filter.h"
1128ffeebbSFabien Dessenne #include "bdisp-reg.h"
1228ffeebbSFabien Dessenne
1328ffeebbSFabien Dessenne /* Max width of the source frame in a single node */
1428ffeebbSFabien Dessenne #define MAX_SRC_WIDTH 2048
1528ffeebbSFabien Dessenne
1628ffeebbSFabien Dessenne /* Reset & boot poll config */
17*bb6d4206SJia-Ju Bai #define POLL_RST_MAX 500
18*bb6d4206SJia-Ju Bai #define POLL_RST_DELAY_MS 2
1928ffeebbSFabien Dessenne
2028ffeebbSFabien Dessenne enum bdisp_target_plan {
2128ffeebbSFabien Dessenne BDISP_RGB,
2228ffeebbSFabien Dessenne BDISP_Y,
2328ffeebbSFabien Dessenne BDISP_CBCR
2428ffeebbSFabien Dessenne };
2528ffeebbSFabien Dessenne
2628ffeebbSFabien Dessenne struct bdisp_op_cfg {
2728ffeebbSFabien Dessenne bool cconv; /* RGB - YUV conversion */
2828ffeebbSFabien Dessenne bool hflip; /* Horizontal flip */
2928ffeebbSFabien Dessenne bool vflip; /* Vertical flip */
3028ffeebbSFabien Dessenne bool wide; /* Wide (>MAX_SRC_WIDTH) */
3128ffeebbSFabien Dessenne bool scale; /* Scale */
3228ffeebbSFabien Dessenne u16 h_inc; /* Horizontal increment in 6.10 format */
3328ffeebbSFabien Dessenne u16 v_inc; /* Vertical increment in 6.10 format */
3428ffeebbSFabien Dessenne bool src_interlaced; /* is the src an interlaced buffer */
3528ffeebbSFabien Dessenne u8 src_nbp; /* nb of planes of the src */
3628ffeebbSFabien Dessenne bool src_yuv; /* is the src a YUV color format */
3728ffeebbSFabien Dessenne bool src_420; /* is the src 4:2:0 chroma subsampled */
3828ffeebbSFabien Dessenne u8 dst_nbp; /* nb of planes of the dst */
3928ffeebbSFabien Dessenne bool dst_yuv; /* is the dst a YUV color format */
4028ffeebbSFabien Dessenne bool dst_420; /* is the dst 4:2:0 chroma subsampled */
4128ffeebbSFabien Dessenne };
4228ffeebbSFabien Dessenne
4328ffeebbSFabien Dessenne struct bdisp_filter_addr {
4428ffeebbSFabien Dessenne u16 min; /* Filter min scale factor (6.10 fixed point) */
4528ffeebbSFabien Dessenne u16 max; /* Filter max scale factor (6.10 fixed point) */
4628ffeebbSFabien Dessenne void *virt; /* Virtual address for filter table */
4728ffeebbSFabien Dessenne dma_addr_t paddr; /* Physical address for filter table */
4828ffeebbSFabien Dessenne };
4928ffeebbSFabien Dessenne
50068adc45SMauro Carvalho Chehab static const struct bdisp_filter_h_spec bdisp_h_spec[] = {
51068adc45SMauro Carvalho Chehab {
52068adc45SMauro Carvalho Chehab .min = 0,
53068adc45SMauro Carvalho Chehab .max = 921,
54068adc45SMauro Carvalho Chehab .coef = {
55068adc45SMauro Carvalho Chehab 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
56068adc45SMauro Carvalho Chehab 0x00, 0x00, 0xff, 0x07, 0x3d, 0xfc, 0x01, 0x00,
57068adc45SMauro Carvalho Chehab 0x00, 0x01, 0xfd, 0x11, 0x36, 0xf9, 0x02, 0x00,
58068adc45SMauro Carvalho Chehab 0x00, 0x01, 0xfb, 0x1b, 0x2e, 0xf9, 0x02, 0x00,
59068adc45SMauro Carvalho Chehab 0x00, 0x01, 0xf9, 0x26, 0x26, 0xf9, 0x01, 0x00,
60068adc45SMauro Carvalho Chehab 0x00, 0x02, 0xf9, 0x30, 0x19, 0xfb, 0x01, 0x00,
61068adc45SMauro Carvalho Chehab 0x00, 0x02, 0xf9, 0x39, 0x0e, 0xfd, 0x01, 0x00,
62068adc45SMauro Carvalho Chehab 0x00, 0x01, 0xfc, 0x3e, 0x06, 0xff, 0x00, 0x00
63068adc45SMauro Carvalho Chehab }
64068adc45SMauro Carvalho Chehab },
65068adc45SMauro Carvalho Chehab {
66068adc45SMauro Carvalho Chehab .min = 921,
67068adc45SMauro Carvalho Chehab .max = 1024,
68068adc45SMauro Carvalho Chehab .coef = {
69068adc45SMauro Carvalho Chehab 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
70068adc45SMauro Carvalho Chehab 0xff, 0x03, 0xfd, 0x08, 0x3e, 0xf9, 0x04, 0xfe,
71068adc45SMauro Carvalho Chehab 0xfd, 0x06, 0xf8, 0x13, 0x3b, 0xf4, 0x07, 0xfc,
72068adc45SMauro Carvalho Chehab 0xfb, 0x08, 0xf5, 0x1f, 0x34, 0xf1, 0x09, 0xfb,
73068adc45SMauro Carvalho Chehab 0xfb, 0x09, 0xf2, 0x2b, 0x2a, 0xf1, 0x09, 0xfb,
74068adc45SMauro Carvalho Chehab 0xfb, 0x09, 0xf2, 0x35, 0x1e, 0xf4, 0x08, 0xfb,
75068adc45SMauro Carvalho Chehab 0xfc, 0x07, 0xf5, 0x3c, 0x12, 0xf7, 0x06, 0xfd,
76068adc45SMauro Carvalho Chehab 0xfe, 0x04, 0xfa, 0x3f, 0x07, 0xfc, 0x03, 0xff
77068adc45SMauro Carvalho Chehab }
78068adc45SMauro Carvalho Chehab },
79068adc45SMauro Carvalho Chehab {
80068adc45SMauro Carvalho Chehab .min = 1024,
81068adc45SMauro Carvalho Chehab .max = 1126,
82068adc45SMauro Carvalho Chehab .coef = {
83068adc45SMauro Carvalho Chehab 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
84068adc45SMauro Carvalho Chehab 0xff, 0x03, 0xfd, 0x08, 0x3e, 0xf9, 0x04, 0xfe,
85068adc45SMauro Carvalho Chehab 0xfd, 0x06, 0xf8, 0x13, 0x3b, 0xf4, 0x07, 0xfc,
86068adc45SMauro Carvalho Chehab 0xfb, 0x08, 0xf5, 0x1f, 0x34, 0xf1, 0x09, 0xfb,
87068adc45SMauro Carvalho Chehab 0xfb, 0x09, 0xf2, 0x2b, 0x2a, 0xf1, 0x09, 0xfb,
88068adc45SMauro Carvalho Chehab 0xfb, 0x09, 0xf2, 0x35, 0x1e, 0xf4, 0x08, 0xfb,
89068adc45SMauro Carvalho Chehab 0xfc, 0x07, 0xf5, 0x3c, 0x12, 0xf7, 0x06, 0xfd,
90068adc45SMauro Carvalho Chehab 0xfe, 0x04, 0xfa, 0x3f, 0x07, 0xfc, 0x03, 0xff
91068adc45SMauro Carvalho Chehab }
92068adc45SMauro Carvalho Chehab },
93068adc45SMauro Carvalho Chehab {
94068adc45SMauro Carvalho Chehab .min = 1126,
95068adc45SMauro Carvalho Chehab .max = 1228,
96068adc45SMauro Carvalho Chehab .coef = {
97068adc45SMauro Carvalho Chehab 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
98068adc45SMauro Carvalho Chehab 0xff, 0x03, 0xfd, 0x08, 0x3e, 0xf9, 0x04, 0xfe,
99068adc45SMauro Carvalho Chehab 0xfd, 0x06, 0xf8, 0x13, 0x3b, 0xf4, 0x07, 0xfc,
100068adc45SMauro Carvalho Chehab 0xfb, 0x08, 0xf5, 0x1f, 0x34, 0xf1, 0x09, 0xfb,
101068adc45SMauro Carvalho Chehab 0xfb, 0x09, 0xf2, 0x2b, 0x2a, 0xf1, 0x09, 0xfb,
102068adc45SMauro Carvalho Chehab 0xfb, 0x09, 0xf2, 0x35, 0x1e, 0xf4, 0x08, 0xfb,
103068adc45SMauro Carvalho Chehab 0xfc, 0x07, 0xf5, 0x3c, 0x12, 0xf7, 0x06, 0xfd,
104068adc45SMauro Carvalho Chehab 0xfe, 0x04, 0xfa, 0x3f, 0x07, 0xfc, 0x03, 0xff
105068adc45SMauro Carvalho Chehab }
106068adc45SMauro Carvalho Chehab },
107068adc45SMauro Carvalho Chehab {
108068adc45SMauro Carvalho Chehab .min = 1228,
109068adc45SMauro Carvalho Chehab .max = 1331,
110068adc45SMauro Carvalho Chehab .coef = {
111068adc45SMauro Carvalho Chehab 0xfd, 0x04, 0xfc, 0x05, 0x39, 0x05, 0xfc, 0x04,
112068adc45SMauro Carvalho Chehab 0xfc, 0x06, 0xf9, 0x0c, 0x39, 0xfe, 0x00, 0x02,
113068adc45SMauro Carvalho Chehab 0xfb, 0x08, 0xf6, 0x17, 0x35, 0xf9, 0x02, 0x00,
114068adc45SMauro Carvalho Chehab 0xfc, 0x08, 0xf4, 0x20, 0x30, 0xf4, 0x05, 0xff,
115068adc45SMauro Carvalho Chehab 0xfd, 0x07, 0xf4, 0x29, 0x28, 0xf3, 0x07, 0xfd,
116068adc45SMauro Carvalho Chehab 0xff, 0x05, 0xf5, 0x31, 0x1f, 0xf3, 0x08, 0xfc,
117068adc45SMauro Carvalho Chehab 0x00, 0x02, 0xf9, 0x38, 0x14, 0xf6, 0x08, 0xfb,
118068adc45SMauro Carvalho Chehab 0x02, 0x00, 0xff, 0x3a, 0x0b, 0xf8, 0x06, 0xfc
119068adc45SMauro Carvalho Chehab }
120068adc45SMauro Carvalho Chehab },
121068adc45SMauro Carvalho Chehab {
122068adc45SMauro Carvalho Chehab .min = 1331,
123068adc45SMauro Carvalho Chehab .max = 1433,
124068adc45SMauro Carvalho Chehab .coef = {
125068adc45SMauro Carvalho Chehab 0xfc, 0x06, 0xf9, 0x09, 0x34, 0x09, 0xf9, 0x06,
126068adc45SMauro Carvalho Chehab 0xfd, 0x07, 0xf7, 0x10, 0x32, 0x02, 0xfc, 0x05,
127068adc45SMauro Carvalho Chehab 0xfe, 0x07, 0xf6, 0x17, 0x2f, 0xfc, 0xff, 0x04,
128068adc45SMauro Carvalho Chehab 0xff, 0x06, 0xf5, 0x20, 0x2a, 0xf9, 0x01, 0x02,
129068adc45SMauro Carvalho Chehab 0x00, 0x04, 0xf6, 0x27, 0x25, 0xf6, 0x04, 0x00,
130068adc45SMauro Carvalho Chehab 0x02, 0x01, 0xf9, 0x2d, 0x1d, 0xf5, 0x06, 0xff,
131068adc45SMauro Carvalho Chehab 0x04, 0xff, 0xfd, 0x31, 0x15, 0xf5, 0x07, 0xfe,
132068adc45SMauro Carvalho Chehab 0x05, 0xfc, 0x02, 0x35, 0x0d, 0xf7, 0x07, 0xfd
133068adc45SMauro Carvalho Chehab }
134068adc45SMauro Carvalho Chehab },
135068adc45SMauro Carvalho Chehab {
136068adc45SMauro Carvalho Chehab .min = 1433,
137068adc45SMauro Carvalho Chehab .max = 1536,
138068adc45SMauro Carvalho Chehab .coef = {
139068adc45SMauro Carvalho Chehab 0xfe, 0x06, 0xf8, 0x0b, 0x30, 0x0b, 0xf8, 0x06,
140068adc45SMauro Carvalho Chehab 0xff, 0x06, 0xf7, 0x12, 0x2d, 0x05, 0xfa, 0x06,
141068adc45SMauro Carvalho Chehab 0x00, 0x04, 0xf6, 0x18, 0x2c, 0x00, 0xfc, 0x06,
142068adc45SMauro Carvalho Chehab 0x01, 0x02, 0xf7, 0x1f, 0x27, 0xfd, 0xff, 0x04,
143068adc45SMauro Carvalho Chehab 0x03, 0x00, 0xf9, 0x24, 0x24, 0xf9, 0x00, 0x03,
144068adc45SMauro Carvalho Chehab 0x04, 0xff, 0xfd, 0x29, 0x1d, 0xf7, 0x02, 0x01,
145068adc45SMauro Carvalho Chehab 0x06, 0xfc, 0x00, 0x2d, 0x17, 0xf6, 0x04, 0x00,
146068adc45SMauro Carvalho Chehab 0x06, 0xfa, 0x05, 0x30, 0x0f, 0xf7, 0x06, 0xff
147068adc45SMauro Carvalho Chehab }
148068adc45SMauro Carvalho Chehab },
149068adc45SMauro Carvalho Chehab {
150068adc45SMauro Carvalho Chehab .min = 1536,
151068adc45SMauro Carvalho Chehab .max = 2048,
152068adc45SMauro Carvalho Chehab .coef = {
153068adc45SMauro Carvalho Chehab 0x05, 0xfd, 0xfb, 0x13, 0x25, 0x13, 0xfb, 0xfd,
154068adc45SMauro Carvalho Chehab 0x05, 0xfc, 0xfd, 0x17, 0x24, 0x0f, 0xf9, 0xff,
155068adc45SMauro Carvalho Chehab 0x04, 0xfa, 0xff, 0x1b, 0x24, 0x0b, 0xf9, 0x00,
156068adc45SMauro Carvalho Chehab 0x03, 0xf9, 0x01, 0x1f, 0x23, 0x08, 0xf8, 0x01,
157068adc45SMauro Carvalho Chehab 0x02, 0xf9, 0x04, 0x22, 0x20, 0x04, 0xf9, 0x02,
158068adc45SMauro Carvalho Chehab 0x01, 0xf8, 0x08, 0x25, 0x1d, 0x01, 0xf9, 0x03,
159068adc45SMauro Carvalho Chehab 0x00, 0xf9, 0x0c, 0x25, 0x1a, 0xfe, 0xfa, 0x04,
160068adc45SMauro Carvalho Chehab 0xff, 0xf9, 0x10, 0x26, 0x15, 0xfc, 0xfc, 0x05
161068adc45SMauro Carvalho Chehab }
162068adc45SMauro Carvalho Chehab },
163068adc45SMauro Carvalho Chehab {
164068adc45SMauro Carvalho Chehab .min = 2048,
165068adc45SMauro Carvalho Chehab .max = 3072,
166068adc45SMauro Carvalho Chehab .coef = {
167068adc45SMauro Carvalho Chehab 0xfc, 0xfd, 0x06, 0x13, 0x18, 0x13, 0x06, 0xfd,
168068adc45SMauro Carvalho Chehab 0xfc, 0xfe, 0x08, 0x15, 0x17, 0x12, 0x04, 0xfc,
169068adc45SMauro Carvalho Chehab 0xfb, 0xfe, 0x0a, 0x16, 0x18, 0x10, 0x03, 0xfc,
170068adc45SMauro Carvalho Chehab 0xfb, 0x00, 0x0b, 0x18, 0x17, 0x0f, 0x01, 0xfb,
171068adc45SMauro Carvalho Chehab 0xfb, 0x00, 0x0d, 0x19, 0x17, 0x0d, 0x00, 0xfb,
172068adc45SMauro Carvalho Chehab 0xfb, 0x01, 0x0f, 0x19, 0x16, 0x0b, 0x00, 0xfb,
173068adc45SMauro Carvalho Chehab 0xfc, 0x03, 0x11, 0x19, 0x15, 0x09, 0xfe, 0xfb,
174068adc45SMauro Carvalho Chehab 0xfc, 0x04, 0x12, 0x1a, 0x12, 0x08, 0xfe, 0xfc
175068adc45SMauro Carvalho Chehab }
176068adc45SMauro Carvalho Chehab },
177068adc45SMauro Carvalho Chehab {
178068adc45SMauro Carvalho Chehab .min = 3072,
179068adc45SMauro Carvalho Chehab .max = 4096,
180068adc45SMauro Carvalho Chehab .coef = {
181068adc45SMauro Carvalho Chehab 0xfe, 0x02, 0x09, 0x0f, 0x0e, 0x0f, 0x09, 0x02,
182068adc45SMauro Carvalho Chehab 0xff, 0x02, 0x09, 0x0f, 0x10, 0x0e, 0x08, 0x01,
183068adc45SMauro Carvalho Chehab 0xff, 0x03, 0x0a, 0x10, 0x10, 0x0d, 0x07, 0x00,
184068adc45SMauro Carvalho Chehab 0x00, 0x04, 0x0b, 0x10, 0x0f, 0x0c, 0x06, 0x00,
185068adc45SMauro Carvalho Chehab 0x00, 0x05, 0x0c, 0x10, 0x0e, 0x0c, 0x05, 0x00,
186068adc45SMauro Carvalho Chehab 0x00, 0x06, 0x0c, 0x11, 0x0e, 0x0b, 0x04, 0x00,
187068adc45SMauro Carvalho Chehab 0x00, 0x07, 0x0d, 0x11, 0x0f, 0x0a, 0x03, 0xff,
188068adc45SMauro Carvalho Chehab 0x01, 0x08, 0x0e, 0x11, 0x0e, 0x09, 0x02, 0xff
189068adc45SMauro Carvalho Chehab }
190068adc45SMauro Carvalho Chehab },
191068adc45SMauro Carvalho Chehab {
192068adc45SMauro Carvalho Chehab .min = 4096,
193068adc45SMauro Carvalho Chehab .max = 5120,
194068adc45SMauro Carvalho Chehab .coef = {
195068adc45SMauro Carvalho Chehab 0x00, 0x04, 0x09, 0x0c, 0x0e, 0x0c, 0x09, 0x04,
196068adc45SMauro Carvalho Chehab 0x01, 0x05, 0x09, 0x0c, 0x0d, 0x0c, 0x08, 0x04,
197068adc45SMauro Carvalho Chehab 0x01, 0x05, 0x0a, 0x0c, 0x0e, 0x0b, 0x08, 0x03,
198068adc45SMauro Carvalho Chehab 0x02, 0x06, 0x0a, 0x0d, 0x0c, 0x0b, 0x07, 0x03,
199068adc45SMauro Carvalho Chehab 0x02, 0x07, 0x0a, 0x0d, 0x0d, 0x0a, 0x07, 0x02,
200068adc45SMauro Carvalho Chehab 0x03, 0x07, 0x0b, 0x0d, 0x0c, 0x0a, 0x06, 0x02,
201068adc45SMauro Carvalho Chehab 0x03, 0x08, 0x0b, 0x0d, 0x0d, 0x0a, 0x05, 0x01,
202068adc45SMauro Carvalho Chehab 0x04, 0x08, 0x0c, 0x0d, 0x0c, 0x09, 0x05, 0x01
203068adc45SMauro Carvalho Chehab }
204068adc45SMauro Carvalho Chehab },
205068adc45SMauro Carvalho Chehab {
206068adc45SMauro Carvalho Chehab .min = 5120,
207068adc45SMauro Carvalho Chehab .max = 65535,
208068adc45SMauro Carvalho Chehab .coef = {
209068adc45SMauro Carvalho Chehab 0x03, 0x06, 0x09, 0x0b, 0x09, 0x0b, 0x09, 0x06,
210068adc45SMauro Carvalho Chehab 0x03, 0x06, 0x09, 0x0b, 0x0c, 0x0a, 0x08, 0x05,
211068adc45SMauro Carvalho Chehab 0x03, 0x06, 0x09, 0x0b, 0x0c, 0x0a, 0x08, 0x05,
212068adc45SMauro Carvalho Chehab 0x04, 0x07, 0x09, 0x0b, 0x0b, 0x0a, 0x08, 0x04,
213068adc45SMauro Carvalho Chehab 0x04, 0x07, 0x0a, 0x0b, 0x0b, 0x0a, 0x07, 0x04,
214068adc45SMauro Carvalho Chehab 0x04, 0x08, 0x0a, 0x0b, 0x0b, 0x09, 0x07, 0x04,
215068adc45SMauro Carvalho Chehab 0x05, 0x08, 0x0a, 0x0b, 0x0c, 0x09, 0x06, 0x03,
216068adc45SMauro Carvalho Chehab 0x05, 0x08, 0x0a, 0x0b, 0x0c, 0x09, 0x06, 0x03
217068adc45SMauro Carvalho Chehab }
218068adc45SMauro Carvalho Chehab }
219068adc45SMauro Carvalho Chehab };
220068adc45SMauro Carvalho Chehab
221068adc45SMauro Carvalho Chehab #define NB_H_FILTER ARRAY_SIZE(bdisp_h_spec)
222068adc45SMauro Carvalho Chehab
223068adc45SMauro Carvalho Chehab
224068adc45SMauro Carvalho Chehab static const struct bdisp_filter_v_spec bdisp_v_spec[] = {
225068adc45SMauro Carvalho Chehab {
226068adc45SMauro Carvalho Chehab .min = 0,
227068adc45SMauro Carvalho Chehab .max = 1024,
228068adc45SMauro Carvalho Chehab .coef = {
229068adc45SMauro Carvalho Chehab 0x00, 0x00, 0x40, 0x00, 0x00,
230068adc45SMauro Carvalho Chehab 0x00, 0x06, 0x3d, 0xfd, 0x00,
231068adc45SMauro Carvalho Chehab 0xfe, 0x0f, 0x38, 0xfb, 0x00,
232068adc45SMauro Carvalho Chehab 0xfd, 0x19, 0x2f, 0xfb, 0x00,
233068adc45SMauro Carvalho Chehab 0xfc, 0x24, 0x24, 0xfc, 0x00,
234068adc45SMauro Carvalho Chehab 0xfb, 0x2f, 0x19, 0xfd, 0x00,
235068adc45SMauro Carvalho Chehab 0xfb, 0x38, 0x0f, 0xfe, 0x00,
236068adc45SMauro Carvalho Chehab 0xfd, 0x3d, 0x06, 0x00, 0x00
237068adc45SMauro Carvalho Chehab }
238068adc45SMauro Carvalho Chehab },
239068adc45SMauro Carvalho Chehab {
240068adc45SMauro Carvalho Chehab .min = 1024,
241068adc45SMauro Carvalho Chehab .max = 1331,
242068adc45SMauro Carvalho Chehab .coef = {
243068adc45SMauro Carvalho Chehab 0xfc, 0x05, 0x3e, 0x05, 0xfc,
244068adc45SMauro Carvalho Chehab 0xf8, 0x0e, 0x3b, 0xff, 0x00,
245068adc45SMauro Carvalho Chehab 0xf5, 0x18, 0x38, 0xf9, 0x02,
246068adc45SMauro Carvalho Chehab 0xf4, 0x21, 0x31, 0xf5, 0x05,
247068adc45SMauro Carvalho Chehab 0xf4, 0x2a, 0x27, 0xf4, 0x07,
248068adc45SMauro Carvalho Chehab 0xf6, 0x30, 0x1e, 0xf4, 0x08,
249068adc45SMauro Carvalho Chehab 0xf9, 0x35, 0x15, 0xf6, 0x07,
250068adc45SMauro Carvalho Chehab 0xff, 0x37, 0x0b, 0xf9, 0x06
251068adc45SMauro Carvalho Chehab }
252068adc45SMauro Carvalho Chehab },
253068adc45SMauro Carvalho Chehab {
254068adc45SMauro Carvalho Chehab .min = 1331,
255068adc45SMauro Carvalho Chehab .max = 1433,
256068adc45SMauro Carvalho Chehab .coef = {
257068adc45SMauro Carvalho Chehab 0xf8, 0x0a, 0x3c, 0x0a, 0xf8,
258068adc45SMauro Carvalho Chehab 0xf6, 0x12, 0x3b, 0x02, 0xfb,
259068adc45SMauro Carvalho Chehab 0xf4, 0x1b, 0x35, 0xfd, 0xff,
260068adc45SMauro Carvalho Chehab 0xf4, 0x23, 0x30, 0xf8, 0x01,
261068adc45SMauro Carvalho Chehab 0xf6, 0x29, 0x27, 0xf6, 0x04,
262068adc45SMauro Carvalho Chehab 0xf9, 0x2e, 0x1e, 0xf5, 0x06,
263068adc45SMauro Carvalho Chehab 0xfd, 0x31, 0x16, 0xf6, 0x06,
264068adc45SMauro Carvalho Chehab 0x02, 0x32, 0x0d, 0xf8, 0x07
265068adc45SMauro Carvalho Chehab }
266068adc45SMauro Carvalho Chehab },
267068adc45SMauro Carvalho Chehab {
268068adc45SMauro Carvalho Chehab .min = 1433,
269068adc45SMauro Carvalho Chehab .max = 1536,
270068adc45SMauro Carvalho Chehab .coef = {
271068adc45SMauro Carvalho Chehab 0xf6, 0x0e, 0x38, 0x0e, 0xf6,
272068adc45SMauro Carvalho Chehab 0xf5, 0x15, 0x38, 0x06, 0xf8,
273068adc45SMauro Carvalho Chehab 0xf5, 0x1d, 0x33, 0x00, 0xfb,
274068adc45SMauro Carvalho Chehab 0xf6, 0x23, 0x2d, 0xfc, 0xfe,
275068adc45SMauro Carvalho Chehab 0xf9, 0x28, 0x26, 0xf9, 0x00,
276068adc45SMauro Carvalho Chehab 0xfc, 0x2c, 0x1e, 0xf7, 0x03,
277068adc45SMauro Carvalho Chehab 0x00, 0x2e, 0x18, 0xf6, 0x04,
278068adc45SMauro Carvalho Chehab 0x05, 0x2e, 0x11, 0xf7, 0x05
279068adc45SMauro Carvalho Chehab }
280068adc45SMauro Carvalho Chehab },
281068adc45SMauro Carvalho Chehab {
282068adc45SMauro Carvalho Chehab .min = 1536,
283068adc45SMauro Carvalho Chehab .max = 2048,
284068adc45SMauro Carvalho Chehab .coef = {
285068adc45SMauro Carvalho Chehab 0xfb, 0x13, 0x24, 0x13, 0xfb,
286068adc45SMauro Carvalho Chehab 0xfd, 0x17, 0x23, 0x0f, 0xfa,
287068adc45SMauro Carvalho Chehab 0xff, 0x1a, 0x23, 0x0b, 0xf9,
288068adc45SMauro Carvalho Chehab 0x01, 0x1d, 0x22, 0x07, 0xf9,
289068adc45SMauro Carvalho Chehab 0x04, 0x20, 0x1f, 0x04, 0xf9,
290068adc45SMauro Carvalho Chehab 0x07, 0x22, 0x1c, 0x01, 0xfa,
291068adc45SMauro Carvalho Chehab 0x0b, 0x24, 0x17, 0xff, 0xfb,
292068adc45SMauro Carvalho Chehab 0x0f, 0x24, 0x14, 0xfd, 0xfc
293068adc45SMauro Carvalho Chehab }
294068adc45SMauro Carvalho Chehab },
295068adc45SMauro Carvalho Chehab {
296068adc45SMauro Carvalho Chehab .min = 2048,
297068adc45SMauro Carvalho Chehab .max = 3072,
298068adc45SMauro Carvalho Chehab .coef = {
299068adc45SMauro Carvalho Chehab 0x05, 0x10, 0x16, 0x10, 0x05,
300068adc45SMauro Carvalho Chehab 0x06, 0x11, 0x16, 0x0f, 0x04,
301068adc45SMauro Carvalho Chehab 0x08, 0x13, 0x15, 0x0e, 0x02,
302068adc45SMauro Carvalho Chehab 0x09, 0x14, 0x16, 0x0c, 0x01,
303068adc45SMauro Carvalho Chehab 0x0b, 0x15, 0x15, 0x0b, 0x00,
304068adc45SMauro Carvalho Chehab 0x0d, 0x16, 0x13, 0x0a, 0x00,
305068adc45SMauro Carvalho Chehab 0x0f, 0x17, 0x13, 0x08, 0xff,
306068adc45SMauro Carvalho Chehab 0x11, 0x18, 0x12, 0x07, 0xfe
307068adc45SMauro Carvalho Chehab }
308068adc45SMauro Carvalho Chehab },
309068adc45SMauro Carvalho Chehab {
310068adc45SMauro Carvalho Chehab .min = 3072,
311068adc45SMauro Carvalho Chehab .max = 4096,
312068adc45SMauro Carvalho Chehab .coef = {
313068adc45SMauro Carvalho Chehab 0x09, 0x0f, 0x10, 0x0f, 0x09,
314068adc45SMauro Carvalho Chehab 0x09, 0x0f, 0x12, 0x0e, 0x08,
315068adc45SMauro Carvalho Chehab 0x0a, 0x10, 0x11, 0x0e, 0x07,
316068adc45SMauro Carvalho Chehab 0x0b, 0x11, 0x11, 0x0d, 0x06,
317068adc45SMauro Carvalho Chehab 0x0c, 0x11, 0x12, 0x0c, 0x05,
318068adc45SMauro Carvalho Chehab 0x0d, 0x12, 0x11, 0x0c, 0x04,
319068adc45SMauro Carvalho Chehab 0x0e, 0x12, 0x11, 0x0b, 0x04,
320068adc45SMauro Carvalho Chehab 0x0f, 0x13, 0x11, 0x0a, 0x03
321068adc45SMauro Carvalho Chehab }
322068adc45SMauro Carvalho Chehab },
323068adc45SMauro Carvalho Chehab {
324068adc45SMauro Carvalho Chehab .min = 4096,
325068adc45SMauro Carvalho Chehab .max = 5120,
326068adc45SMauro Carvalho Chehab .coef = {
327068adc45SMauro Carvalho Chehab 0x0a, 0x0e, 0x10, 0x0e, 0x0a,
328068adc45SMauro Carvalho Chehab 0x0b, 0x0e, 0x0f, 0x0e, 0x0a,
329068adc45SMauro Carvalho Chehab 0x0b, 0x0f, 0x10, 0x0d, 0x09,
330068adc45SMauro Carvalho Chehab 0x0c, 0x0f, 0x10, 0x0d, 0x08,
331068adc45SMauro Carvalho Chehab 0x0d, 0x0f, 0x0f, 0x0d, 0x08,
332068adc45SMauro Carvalho Chehab 0x0d, 0x10, 0x10, 0x0c, 0x07,
333068adc45SMauro Carvalho Chehab 0x0e, 0x10, 0x0f, 0x0c, 0x07,
334068adc45SMauro Carvalho Chehab 0x0f, 0x10, 0x10, 0x0b, 0x06
335068adc45SMauro Carvalho Chehab }
336068adc45SMauro Carvalho Chehab },
337068adc45SMauro Carvalho Chehab {
338068adc45SMauro Carvalho Chehab .min = 5120,
339068adc45SMauro Carvalho Chehab .max = 65535,
340068adc45SMauro Carvalho Chehab .coef = {
341068adc45SMauro Carvalho Chehab 0x0b, 0x0e, 0x0e, 0x0e, 0x0b,
342068adc45SMauro Carvalho Chehab 0x0b, 0x0e, 0x0f, 0x0d, 0x0b,
343068adc45SMauro Carvalho Chehab 0x0c, 0x0e, 0x0f, 0x0d, 0x0a,
344068adc45SMauro Carvalho Chehab 0x0c, 0x0e, 0x0f, 0x0d, 0x0a,
345068adc45SMauro Carvalho Chehab 0x0d, 0x0f, 0x0e, 0x0d, 0x09,
346068adc45SMauro Carvalho Chehab 0x0d, 0x0f, 0x0f, 0x0c, 0x09,
347068adc45SMauro Carvalho Chehab 0x0e, 0x0f, 0x0e, 0x0c, 0x09,
348068adc45SMauro Carvalho Chehab 0x0e, 0x0f, 0x0f, 0x0c, 0x08
349068adc45SMauro Carvalho Chehab }
350068adc45SMauro Carvalho Chehab }
351068adc45SMauro Carvalho Chehab };
352068adc45SMauro Carvalho Chehab
353068adc45SMauro Carvalho Chehab #define NB_V_FILTER ARRAY_SIZE(bdisp_v_spec)
354068adc45SMauro Carvalho Chehab
35528ffeebbSFabien Dessenne static struct bdisp_filter_addr bdisp_h_filter[NB_H_FILTER];
35628ffeebbSFabien Dessenne static struct bdisp_filter_addr bdisp_v_filter[NB_V_FILTER];
35728ffeebbSFabien Dessenne
35828ffeebbSFabien Dessenne /**
35928ffeebbSFabien Dessenne * bdisp_hw_reset
36028ffeebbSFabien Dessenne * @bdisp: bdisp entity
36128ffeebbSFabien Dessenne *
36228ffeebbSFabien Dessenne * Resets HW
36328ffeebbSFabien Dessenne *
36428ffeebbSFabien Dessenne * RETURNS:
36528ffeebbSFabien Dessenne * 0 on success.
36628ffeebbSFabien Dessenne */
bdisp_hw_reset(struct bdisp_dev * bdisp)36728ffeebbSFabien Dessenne int bdisp_hw_reset(struct bdisp_dev *bdisp)
36828ffeebbSFabien Dessenne {
36928ffeebbSFabien Dessenne unsigned int i;
37028ffeebbSFabien Dessenne
37128ffeebbSFabien Dessenne dev_dbg(bdisp->dev, "%s\n", __func__);
37228ffeebbSFabien Dessenne
37328ffeebbSFabien Dessenne /* Mask Interrupt */
37428ffeebbSFabien Dessenne writel(0, bdisp->regs + BLT_ITM0);
37528ffeebbSFabien Dessenne
37628ffeebbSFabien Dessenne /* Reset */
37728ffeebbSFabien Dessenne writel(readl(bdisp->regs + BLT_CTL) | BLT_CTL_RESET,
37828ffeebbSFabien Dessenne bdisp->regs + BLT_CTL);
37928ffeebbSFabien Dessenne writel(0, bdisp->regs + BLT_CTL);
38028ffeebbSFabien Dessenne
38128ffeebbSFabien Dessenne /* Wait for reset done */
38228ffeebbSFabien Dessenne for (i = 0; i < POLL_RST_MAX; i++) {
38328ffeebbSFabien Dessenne if (readl(bdisp->regs + BLT_STA1) & BLT_STA1_IDLE)
38428ffeebbSFabien Dessenne break;
385*bb6d4206SJia-Ju Bai udelay(POLL_RST_DELAY_MS * 1000);
38628ffeebbSFabien Dessenne }
38728ffeebbSFabien Dessenne if (i == POLL_RST_MAX)
38828ffeebbSFabien Dessenne dev_err(bdisp->dev, "Reset timeout\n");
38928ffeebbSFabien Dessenne
39028ffeebbSFabien Dessenne return (i == POLL_RST_MAX) ? -EAGAIN : 0;
39128ffeebbSFabien Dessenne }
39228ffeebbSFabien Dessenne
39328ffeebbSFabien Dessenne /**
39428ffeebbSFabien Dessenne * bdisp_hw_get_and_clear_irq
39528ffeebbSFabien Dessenne * @bdisp: bdisp entity
39628ffeebbSFabien Dessenne *
39728ffeebbSFabien Dessenne * Read then reset interrupt status
39828ffeebbSFabien Dessenne *
39928ffeebbSFabien Dessenne * RETURNS:
40028ffeebbSFabien Dessenne * 0 if expected interrupt was raised.
40128ffeebbSFabien Dessenne */
bdisp_hw_get_and_clear_irq(struct bdisp_dev * bdisp)40228ffeebbSFabien Dessenne int bdisp_hw_get_and_clear_irq(struct bdisp_dev *bdisp)
40328ffeebbSFabien Dessenne {
40428ffeebbSFabien Dessenne u32 its;
40528ffeebbSFabien Dessenne
40628ffeebbSFabien Dessenne its = readl(bdisp->regs + BLT_ITS);
40728ffeebbSFabien Dessenne
40828ffeebbSFabien Dessenne /* Check for the only expected IT: LastNode of AQ1 */
40928ffeebbSFabien Dessenne if (!(its & BLT_ITS_AQ1_LNA)) {
41028ffeebbSFabien Dessenne dev_dbg(bdisp->dev, "Unexpected IT status: 0x%08X\n", its);
41128ffeebbSFabien Dessenne writel(its, bdisp->regs + BLT_ITS);
41228ffeebbSFabien Dessenne return -1;
41328ffeebbSFabien Dessenne }
41428ffeebbSFabien Dessenne
41528ffeebbSFabien Dessenne /* Clear and mask */
41628ffeebbSFabien Dessenne writel(its, bdisp->regs + BLT_ITS);
41728ffeebbSFabien Dessenne writel(0, bdisp->regs + BLT_ITM0);
41828ffeebbSFabien Dessenne
41928ffeebbSFabien Dessenne return 0;
42028ffeebbSFabien Dessenne }
42128ffeebbSFabien Dessenne
42228ffeebbSFabien Dessenne /**
42328ffeebbSFabien Dessenne * bdisp_hw_free_nodes
42428ffeebbSFabien Dessenne * @ctx: bdisp context
42528ffeebbSFabien Dessenne *
42628ffeebbSFabien Dessenne * Free node memory
42728ffeebbSFabien Dessenne *
42828ffeebbSFabien Dessenne * RETURNS:
42928ffeebbSFabien Dessenne * None
43028ffeebbSFabien Dessenne */
bdisp_hw_free_nodes(struct bdisp_ctx * ctx)43128ffeebbSFabien Dessenne void bdisp_hw_free_nodes(struct bdisp_ctx *ctx)
43228ffeebbSFabien Dessenne {
43300085f1eSKrzysztof Kozlowski if (ctx && ctx->node[0])
43428ffeebbSFabien Dessenne dma_free_attrs(ctx->bdisp_dev->dev,
43528ffeebbSFabien Dessenne sizeof(struct bdisp_node) * MAX_NB_NODE,
43600085f1eSKrzysztof Kozlowski ctx->node[0], ctx->node_paddr[0],
43700085f1eSKrzysztof Kozlowski DMA_ATTR_WRITE_COMBINE);
43828ffeebbSFabien Dessenne }
43928ffeebbSFabien Dessenne
44028ffeebbSFabien Dessenne /**
44128ffeebbSFabien Dessenne * bdisp_hw_alloc_nodes
44228ffeebbSFabien Dessenne * @ctx: bdisp context
44328ffeebbSFabien Dessenne *
44428ffeebbSFabien Dessenne * Allocate dma memory for nodes
44528ffeebbSFabien Dessenne *
44628ffeebbSFabien Dessenne * RETURNS:
44728ffeebbSFabien Dessenne * 0 on success
44828ffeebbSFabien Dessenne */
bdisp_hw_alloc_nodes(struct bdisp_ctx * ctx)44928ffeebbSFabien Dessenne int bdisp_hw_alloc_nodes(struct bdisp_ctx *ctx)
45028ffeebbSFabien Dessenne {
45128ffeebbSFabien Dessenne struct device *dev = ctx->bdisp_dev->dev;
45228ffeebbSFabien Dessenne unsigned int i, node_size = sizeof(struct bdisp_node);
45328ffeebbSFabien Dessenne void *base;
45428ffeebbSFabien Dessenne dma_addr_t paddr;
45528ffeebbSFabien Dessenne
45628ffeebbSFabien Dessenne /* Allocate all the nodes within a single memory page */
45728ffeebbSFabien Dessenne base = dma_alloc_attrs(dev, node_size * MAX_NB_NODE, &paddr,
4582732bb76SFabien Dessenne GFP_KERNEL, DMA_ATTR_WRITE_COMBINE);
45928ffeebbSFabien Dessenne if (!base) {
46028ffeebbSFabien Dessenne dev_err(dev, "%s no mem\n", __func__);
46128ffeebbSFabien Dessenne return -ENOMEM;
46228ffeebbSFabien Dessenne }
46328ffeebbSFabien Dessenne
46428ffeebbSFabien Dessenne memset(base, 0, node_size * MAX_NB_NODE);
46528ffeebbSFabien Dessenne
46628ffeebbSFabien Dessenne for (i = 0; i < MAX_NB_NODE; i++) {
46728ffeebbSFabien Dessenne ctx->node[i] = base;
46828ffeebbSFabien Dessenne ctx->node_paddr[i] = paddr;
46928ffeebbSFabien Dessenne dev_dbg(dev, "node[%d]=0x%p (paddr=%pad)\n", i, ctx->node[i],
47028ffeebbSFabien Dessenne &paddr);
47128ffeebbSFabien Dessenne base += node_size;
47228ffeebbSFabien Dessenne paddr += node_size;
47328ffeebbSFabien Dessenne }
47428ffeebbSFabien Dessenne
47528ffeebbSFabien Dessenne return 0;
47628ffeebbSFabien Dessenne }
47728ffeebbSFabien Dessenne
47828ffeebbSFabien Dessenne /**
47928ffeebbSFabien Dessenne * bdisp_hw_free_filters
48028ffeebbSFabien Dessenne * @dev: device
48128ffeebbSFabien Dessenne *
48228ffeebbSFabien Dessenne * Free filters memory
48328ffeebbSFabien Dessenne *
48428ffeebbSFabien Dessenne * RETURNS:
48528ffeebbSFabien Dessenne * None
48628ffeebbSFabien Dessenne */
bdisp_hw_free_filters(struct device * dev)48728ffeebbSFabien Dessenne void bdisp_hw_free_filters(struct device *dev)
48828ffeebbSFabien Dessenne {
48928ffeebbSFabien Dessenne int size = (BDISP_HF_NB * NB_H_FILTER) + (BDISP_VF_NB * NB_V_FILTER);
49028ffeebbSFabien Dessenne
49100085f1eSKrzysztof Kozlowski if (bdisp_h_filter[0].virt)
49228ffeebbSFabien Dessenne dma_free_attrs(dev, size, bdisp_h_filter[0].virt,
49300085f1eSKrzysztof Kozlowski bdisp_h_filter[0].paddr, DMA_ATTR_WRITE_COMBINE);
49428ffeebbSFabien Dessenne }
49528ffeebbSFabien Dessenne
49628ffeebbSFabien Dessenne /**
49728ffeebbSFabien Dessenne * bdisp_hw_alloc_filters
49828ffeebbSFabien Dessenne * @dev: device
49928ffeebbSFabien Dessenne *
50028ffeebbSFabien Dessenne * Allocate dma memory for filters
50128ffeebbSFabien Dessenne *
50228ffeebbSFabien Dessenne * RETURNS:
50328ffeebbSFabien Dessenne * 0 on success
50428ffeebbSFabien Dessenne */
bdisp_hw_alloc_filters(struct device * dev)50528ffeebbSFabien Dessenne int bdisp_hw_alloc_filters(struct device *dev)
50628ffeebbSFabien Dessenne {
50728ffeebbSFabien Dessenne unsigned int i, size;
50828ffeebbSFabien Dessenne void *base;
50928ffeebbSFabien Dessenne dma_addr_t paddr;
51028ffeebbSFabien Dessenne
51128ffeebbSFabien Dessenne /* Allocate all the filters within a single memory page */
51228ffeebbSFabien Dessenne size = (BDISP_HF_NB * NB_H_FILTER) + (BDISP_VF_NB * NB_V_FILTER);
5133cd6954cSChristoph Hellwig base = dma_alloc_attrs(dev, size, &paddr, GFP_KERNEL,
51400085f1eSKrzysztof Kozlowski DMA_ATTR_WRITE_COMBINE);
51528ffeebbSFabien Dessenne if (!base)
51628ffeebbSFabien Dessenne return -ENOMEM;
51728ffeebbSFabien Dessenne
51828ffeebbSFabien Dessenne /* Setup filter addresses */
51928ffeebbSFabien Dessenne for (i = 0; i < NB_H_FILTER; i++) {
52028ffeebbSFabien Dessenne bdisp_h_filter[i].min = bdisp_h_spec[i].min;
52128ffeebbSFabien Dessenne bdisp_h_filter[i].max = bdisp_h_spec[i].max;
52228ffeebbSFabien Dessenne memcpy(base, bdisp_h_spec[i].coef, BDISP_HF_NB);
52328ffeebbSFabien Dessenne bdisp_h_filter[i].virt = base;
52428ffeebbSFabien Dessenne bdisp_h_filter[i].paddr = paddr;
52528ffeebbSFabien Dessenne base += BDISP_HF_NB;
52628ffeebbSFabien Dessenne paddr += BDISP_HF_NB;
52728ffeebbSFabien Dessenne }
52828ffeebbSFabien Dessenne
52928ffeebbSFabien Dessenne for (i = 0; i < NB_V_FILTER; i++) {
53028ffeebbSFabien Dessenne bdisp_v_filter[i].min = bdisp_v_spec[i].min;
53128ffeebbSFabien Dessenne bdisp_v_filter[i].max = bdisp_v_spec[i].max;
53228ffeebbSFabien Dessenne memcpy(base, bdisp_v_spec[i].coef, BDISP_VF_NB);
53328ffeebbSFabien Dessenne bdisp_v_filter[i].virt = base;
53428ffeebbSFabien Dessenne bdisp_v_filter[i].paddr = paddr;
53528ffeebbSFabien Dessenne base += BDISP_VF_NB;
53628ffeebbSFabien Dessenne paddr += BDISP_VF_NB;
53728ffeebbSFabien Dessenne }
53828ffeebbSFabien Dessenne
53928ffeebbSFabien Dessenne return 0;
54028ffeebbSFabien Dessenne }
54128ffeebbSFabien Dessenne
54228ffeebbSFabien Dessenne /**
54328ffeebbSFabien Dessenne * bdisp_hw_get_hf_addr
54428ffeebbSFabien Dessenne * @inc: resize increment
54528ffeebbSFabien Dessenne *
54628ffeebbSFabien Dessenne * Find the horizontal filter table that fits the resize increment
54728ffeebbSFabien Dessenne *
54828ffeebbSFabien Dessenne * RETURNS:
54928ffeebbSFabien Dessenne * table physical address
55028ffeebbSFabien Dessenne */
bdisp_hw_get_hf_addr(u16 inc)55128ffeebbSFabien Dessenne static dma_addr_t bdisp_hw_get_hf_addr(u16 inc)
55228ffeebbSFabien Dessenne {
55328ffeebbSFabien Dessenne unsigned int i;
55428ffeebbSFabien Dessenne
55528ffeebbSFabien Dessenne for (i = NB_H_FILTER - 1; i > 0; i--)
55628ffeebbSFabien Dessenne if ((bdisp_h_filter[i].min < inc) &&
55728ffeebbSFabien Dessenne (inc <= bdisp_h_filter[i].max))
55828ffeebbSFabien Dessenne break;
55928ffeebbSFabien Dessenne
56028ffeebbSFabien Dessenne return bdisp_h_filter[i].paddr;
56128ffeebbSFabien Dessenne }
56228ffeebbSFabien Dessenne
56328ffeebbSFabien Dessenne /**
56428ffeebbSFabien Dessenne * bdisp_hw_get_vf_addr
56528ffeebbSFabien Dessenne * @inc: resize increment
56628ffeebbSFabien Dessenne *
56728ffeebbSFabien Dessenne * Find the vertical filter table that fits the resize increment
56828ffeebbSFabien Dessenne *
56928ffeebbSFabien Dessenne * RETURNS:
57028ffeebbSFabien Dessenne * table physical address
57128ffeebbSFabien Dessenne */
bdisp_hw_get_vf_addr(u16 inc)57228ffeebbSFabien Dessenne static dma_addr_t bdisp_hw_get_vf_addr(u16 inc)
57328ffeebbSFabien Dessenne {
57428ffeebbSFabien Dessenne unsigned int i;
57528ffeebbSFabien Dessenne
57628ffeebbSFabien Dessenne for (i = NB_V_FILTER - 1; i > 0; i--)
57728ffeebbSFabien Dessenne if ((bdisp_v_filter[i].min < inc) &&
57828ffeebbSFabien Dessenne (inc <= bdisp_v_filter[i].max))
57928ffeebbSFabien Dessenne break;
58028ffeebbSFabien Dessenne
58128ffeebbSFabien Dessenne return bdisp_v_filter[i].paddr;
58228ffeebbSFabien Dessenne }
58328ffeebbSFabien Dessenne
58428ffeebbSFabien Dessenne /**
58528ffeebbSFabien Dessenne * bdisp_hw_get_inc
58628ffeebbSFabien Dessenne * @from: input size
58728ffeebbSFabien Dessenne * @to: output size
58828ffeebbSFabien Dessenne * @inc: resize increment in 6.10 format
58928ffeebbSFabien Dessenne *
59028ffeebbSFabien Dessenne * Computes the increment (inverse of scale) in 6.10 format
59128ffeebbSFabien Dessenne *
59228ffeebbSFabien Dessenne * RETURNS:
59328ffeebbSFabien Dessenne * 0 on success
59428ffeebbSFabien Dessenne */
bdisp_hw_get_inc(u32 from,u32 to,u16 * inc)59528ffeebbSFabien Dessenne static int bdisp_hw_get_inc(u32 from, u32 to, u16 *inc)
59628ffeebbSFabien Dessenne {
59728ffeebbSFabien Dessenne u32 tmp;
59828ffeebbSFabien Dessenne
59928ffeebbSFabien Dessenne if (!to)
60028ffeebbSFabien Dessenne return -EINVAL;
60128ffeebbSFabien Dessenne
60228ffeebbSFabien Dessenne if (to == from) {
60328ffeebbSFabien Dessenne *inc = 1 << 10;
60428ffeebbSFabien Dessenne return 0;
60528ffeebbSFabien Dessenne }
60628ffeebbSFabien Dessenne
60728ffeebbSFabien Dessenne tmp = (from << 10) / to;
60828ffeebbSFabien Dessenne if ((tmp > 0xFFFF) || (!tmp))
60928ffeebbSFabien Dessenne /* overflow (downscale x 63) or too small (upscale x 1024) */
61028ffeebbSFabien Dessenne return -EINVAL;
61128ffeebbSFabien Dessenne
61228ffeebbSFabien Dessenne *inc = (u16)tmp;
61328ffeebbSFabien Dessenne
61428ffeebbSFabien Dessenne return 0;
61528ffeebbSFabien Dessenne }
61628ffeebbSFabien Dessenne
61728ffeebbSFabien Dessenne /**
61828ffeebbSFabien Dessenne * bdisp_hw_get_hv_inc
61928ffeebbSFabien Dessenne * @ctx: device context
62028ffeebbSFabien Dessenne * @h_inc: horizontal increment
62128ffeebbSFabien Dessenne * @v_inc: vertical increment
62228ffeebbSFabien Dessenne *
62328ffeebbSFabien Dessenne * Computes the horizontal & vertical increments (inverse of scale)
62428ffeebbSFabien Dessenne *
62528ffeebbSFabien Dessenne * RETURNS:
62628ffeebbSFabien Dessenne * 0 on success
62728ffeebbSFabien Dessenne */
bdisp_hw_get_hv_inc(struct bdisp_ctx * ctx,u16 * h_inc,u16 * v_inc)62828ffeebbSFabien Dessenne static int bdisp_hw_get_hv_inc(struct bdisp_ctx *ctx, u16 *h_inc, u16 *v_inc)
62928ffeebbSFabien Dessenne {
63028ffeebbSFabien Dessenne u32 src_w, src_h, dst_w, dst_h;
63128ffeebbSFabien Dessenne
63228ffeebbSFabien Dessenne src_w = ctx->src.crop.width;
63328ffeebbSFabien Dessenne src_h = ctx->src.crop.height;
6343d8bffe8SFabien Dessenne dst_w = ctx->dst.crop.width;
6353d8bffe8SFabien Dessenne dst_h = ctx->dst.crop.height;
63628ffeebbSFabien Dessenne
63728ffeebbSFabien Dessenne if (bdisp_hw_get_inc(src_w, dst_w, h_inc) ||
63828ffeebbSFabien Dessenne bdisp_hw_get_inc(src_h, dst_h, v_inc)) {
63928ffeebbSFabien Dessenne dev_err(ctx->bdisp_dev->dev,
64028ffeebbSFabien Dessenne "scale factors failed (%dx%d)->(%dx%d)\n",
64128ffeebbSFabien Dessenne src_w, src_h, dst_w, dst_h);
64228ffeebbSFabien Dessenne return -EINVAL;
64328ffeebbSFabien Dessenne }
64428ffeebbSFabien Dessenne
64528ffeebbSFabien Dessenne return 0;
64628ffeebbSFabien Dessenne }
64728ffeebbSFabien Dessenne
64828ffeebbSFabien Dessenne /**
64928ffeebbSFabien Dessenne * bdisp_hw_get_op_cfg
65028ffeebbSFabien Dessenne * @ctx: device context
65128ffeebbSFabien Dessenne * @c: operation configuration
65228ffeebbSFabien Dessenne *
65328ffeebbSFabien Dessenne * Check which blitter operations are expected and sets the scaling increments
65428ffeebbSFabien Dessenne *
65528ffeebbSFabien Dessenne * RETURNS:
65628ffeebbSFabien Dessenne * 0 on success
65728ffeebbSFabien Dessenne */
bdisp_hw_get_op_cfg(struct bdisp_ctx * ctx,struct bdisp_op_cfg * c)65828ffeebbSFabien Dessenne static int bdisp_hw_get_op_cfg(struct bdisp_ctx *ctx, struct bdisp_op_cfg *c)
65928ffeebbSFabien Dessenne {
66028ffeebbSFabien Dessenne struct device *dev = ctx->bdisp_dev->dev;
66128ffeebbSFabien Dessenne struct bdisp_frame *src = &ctx->src;
66228ffeebbSFabien Dessenne struct bdisp_frame *dst = &ctx->dst;
66328ffeebbSFabien Dessenne
66428ffeebbSFabien Dessenne if (src->width > MAX_SRC_WIDTH * MAX_VERTICAL_STRIDES) {
66528ffeebbSFabien Dessenne dev_err(dev, "Image width out of HW caps\n");
66628ffeebbSFabien Dessenne return -EINVAL;
66728ffeebbSFabien Dessenne }
66828ffeebbSFabien Dessenne
66928ffeebbSFabien Dessenne c->wide = src->width > MAX_SRC_WIDTH;
67028ffeebbSFabien Dessenne
67128ffeebbSFabien Dessenne c->hflip = ctx->hflip;
67228ffeebbSFabien Dessenne c->vflip = ctx->vflip;
67328ffeebbSFabien Dessenne
67428ffeebbSFabien Dessenne c->src_interlaced = (src->field == V4L2_FIELD_INTERLACED);
67528ffeebbSFabien Dessenne
67628ffeebbSFabien Dessenne c->src_nbp = src->fmt->nb_planes;
67728ffeebbSFabien Dessenne c->src_yuv = (src->fmt->pixelformat == V4L2_PIX_FMT_NV12) ||
67828ffeebbSFabien Dessenne (src->fmt->pixelformat == V4L2_PIX_FMT_YUV420);
67928ffeebbSFabien Dessenne c->src_420 = c->src_yuv;
68028ffeebbSFabien Dessenne
68128ffeebbSFabien Dessenne c->dst_nbp = dst->fmt->nb_planes;
68228ffeebbSFabien Dessenne c->dst_yuv = (dst->fmt->pixelformat == V4L2_PIX_FMT_NV12) ||
68328ffeebbSFabien Dessenne (dst->fmt->pixelformat == V4L2_PIX_FMT_YUV420);
68428ffeebbSFabien Dessenne c->dst_420 = c->dst_yuv;
68528ffeebbSFabien Dessenne
68628ffeebbSFabien Dessenne c->cconv = (c->src_yuv != c->dst_yuv);
68728ffeebbSFabien Dessenne
68828ffeebbSFabien Dessenne if (bdisp_hw_get_hv_inc(ctx, &c->h_inc, &c->v_inc)) {
68928ffeebbSFabien Dessenne dev_err(dev, "Scale factor out of HW caps\n");
69028ffeebbSFabien Dessenne return -EINVAL;
69128ffeebbSFabien Dessenne }
69228ffeebbSFabien Dessenne
69328ffeebbSFabien Dessenne /* Deinterlacing adjustment : stretch a field to a frame */
69428ffeebbSFabien Dessenne if (c->src_interlaced)
69528ffeebbSFabien Dessenne c->v_inc /= 2;
69628ffeebbSFabien Dessenne
69728ffeebbSFabien Dessenne if ((c->h_inc != (1 << 10)) || (c->v_inc != (1 << 10)))
69828ffeebbSFabien Dessenne c->scale = true;
69928ffeebbSFabien Dessenne else
70028ffeebbSFabien Dessenne c->scale = false;
70128ffeebbSFabien Dessenne
70228ffeebbSFabien Dessenne return 0;
70328ffeebbSFabien Dessenne }
70428ffeebbSFabien Dessenne
70528ffeebbSFabien Dessenne /**
70628ffeebbSFabien Dessenne * bdisp_hw_color_format
70728ffeebbSFabien Dessenne * @pixelformat: v4l2 pixel format
70828ffeebbSFabien Dessenne *
70928ffeebbSFabien Dessenne * v4l2 to bdisp pixel format convert
71028ffeebbSFabien Dessenne *
71128ffeebbSFabien Dessenne * RETURNS:
71228ffeebbSFabien Dessenne * bdisp pixel format
71328ffeebbSFabien Dessenne */
bdisp_hw_color_format(u32 pixelformat)71428ffeebbSFabien Dessenne static u32 bdisp_hw_color_format(u32 pixelformat)
71528ffeebbSFabien Dessenne {
71628ffeebbSFabien Dessenne u32 ret;
71728ffeebbSFabien Dessenne
71828ffeebbSFabien Dessenne switch (pixelformat) {
71928ffeebbSFabien Dessenne case V4L2_PIX_FMT_YUV420:
72028ffeebbSFabien Dessenne ret = (BDISP_YUV_3B << BLT_TTY_COL_SHIFT);
72128ffeebbSFabien Dessenne break;
72228ffeebbSFabien Dessenne case V4L2_PIX_FMT_NV12:
72328ffeebbSFabien Dessenne ret = (BDISP_NV12 << BLT_TTY_COL_SHIFT) | BLT_TTY_BIG_END;
72428ffeebbSFabien Dessenne break;
72528ffeebbSFabien Dessenne case V4L2_PIX_FMT_RGB565:
72628ffeebbSFabien Dessenne ret = (BDISP_RGB565 << BLT_TTY_COL_SHIFT);
72728ffeebbSFabien Dessenne break;
72828ffeebbSFabien Dessenne case V4L2_PIX_FMT_XBGR32: /* This V4L format actually refers to xRGB */
72928ffeebbSFabien Dessenne ret = (BDISP_XRGB8888 << BLT_TTY_COL_SHIFT);
73028ffeebbSFabien Dessenne break;
73128ffeebbSFabien Dessenne case V4L2_PIX_FMT_RGB24: /* RGB888 format */
73228ffeebbSFabien Dessenne ret = (BDISP_RGB888 << BLT_TTY_COL_SHIFT) | BLT_TTY_BIG_END;
73328ffeebbSFabien Dessenne break;
73428ffeebbSFabien Dessenne case V4L2_PIX_FMT_ABGR32: /* This V4L format actually refers to ARGB */
73528ffeebbSFabien Dessenne
73628ffeebbSFabien Dessenne default:
73728ffeebbSFabien Dessenne ret = (BDISP_ARGB8888 << BLT_TTY_COL_SHIFT) | BLT_TTY_ALPHA_R;
73828ffeebbSFabien Dessenne break;
73928ffeebbSFabien Dessenne }
74028ffeebbSFabien Dessenne
74128ffeebbSFabien Dessenne return ret;
74228ffeebbSFabien Dessenne }
74328ffeebbSFabien Dessenne
74428ffeebbSFabien Dessenne /**
74528ffeebbSFabien Dessenne * bdisp_hw_build_node
74628ffeebbSFabien Dessenne * @ctx: device context
74728ffeebbSFabien Dessenne * @cfg: operation configuration
74828ffeebbSFabien Dessenne * @node: node to be set
74928ffeebbSFabien Dessenne * @t_plan: whether the node refers to a RGB/Y or a CbCr plane
75028ffeebbSFabien Dessenne * @src_x_offset: x offset in the source image
75128ffeebbSFabien Dessenne *
75228ffeebbSFabien Dessenne * Build a node
75328ffeebbSFabien Dessenne *
75428ffeebbSFabien Dessenne * RETURNS:
75528ffeebbSFabien Dessenne * None
75628ffeebbSFabien Dessenne */
bdisp_hw_build_node(struct bdisp_ctx * ctx,struct bdisp_op_cfg * cfg,struct bdisp_node * node,enum bdisp_target_plan t_plan,int src_x_offset)75728ffeebbSFabien Dessenne static void bdisp_hw_build_node(struct bdisp_ctx *ctx,
75828ffeebbSFabien Dessenne struct bdisp_op_cfg *cfg,
75928ffeebbSFabien Dessenne struct bdisp_node *node,
76028ffeebbSFabien Dessenne enum bdisp_target_plan t_plan, int src_x_offset)
76128ffeebbSFabien Dessenne {
76228ffeebbSFabien Dessenne struct bdisp_frame *src = &ctx->src;
76328ffeebbSFabien Dessenne struct bdisp_frame *dst = &ctx->dst;
76428ffeebbSFabien Dessenne u16 h_inc, v_inc, yh_inc, yv_inc;
76528ffeebbSFabien Dessenne struct v4l2_rect src_rect = src->crop;
76628ffeebbSFabien Dessenne struct v4l2_rect dst_rect = dst->crop;
76728ffeebbSFabien Dessenne int dst_x_offset;
76828ffeebbSFabien Dessenne s32 dst_width = dst->crop.width;
76928ffeebbSFabien Dessenne u32 src_fmt, dst_fmt;
77028ffeebbSFabien Dessenne const u32 *ivmx;
77128ffeebbSFabien Dessenne
77228ffeebbSFabien Dessenne dev_dbg(ctx->bdisp_dev->dev, "%s\n", __func__);
77328ffeebbSFabien Dessenne
77428ffeebbSFabien Dessenne memset(node, 0, sizeof(*node));
77528ffeebbSFabien Dessenne
77628ffeebbSFabien Dessenne /* Adjust src and dst areas wrt src_x_offset */
77728ffeebbSFabien Dessenne src_rect.left += src_x_offset;
77828ffeebbSFabien Dessenne src_rect.width -= src_x_offset;
77928ffeebbSFabien Dessenne src_rect.width = min_t(__s32, MAX_SRC_WIDTH, src_rect.width);
78028ffeebbSFabien Dessenne
7813d8bffe8SFabien Dessenne dst_x_offset = (src_x_offset * dst_width) / ctx->src.crop.width;
78228ffeebbSFabien Dessenne dst_rect.left += dst_x_offset;
7833d8bffe8SFabien Dessenne dst_rect.width = (src_rect.width * dst_width) / ctx->src.crop.width;
78428ffeebbSFabien Dessenne
78528ffeebbSFabien Dessenne /* General */
78628ffeebbSFabien Dessenne src_fmt = src->fmt->pixelformat;
78728ffeebbSFabien Dessenne dst_fmt = dst->fmt->pixelformat;
78828ffeebbSFabien Dessenne
78928ffeebbSFabien Dessenne node->nip = 0;
79028ffeebbSFabien Dessenne node->cic = BLT_CIC_ALL_GRP;
79128ffeebbSFabien Dessenne node->ack = BLT_ACK_BYPASS_S2S3;
79228ffeebbSFabien Dessenne
79328ffeebbSFabien Dessenne switch (cfg->src_nbp) {
79428ffeebbSFabien Dessenne case 1:
79528ffeebbSFabien Dessenne /* Src2 = RGB / Src1 = Src3 = off */
79628ffeebbSFabien Dessenne node->ins = BLT_INS_S1_OFF | BLT_INS_S2_MEM | BLT_INS_S3_OFF;
79728ffeebbSFabien Dessenne break;
79828ffeebbSFabien Dessenne case 2:
79928ffeebbSFabien Dessenne /* Src3 = Y
80028ffeebbSFabien Dessenne * Src2 = CbCr or ColorFill if writing the Y plane
80128ffeebbSFabien Dessenne * Src1 = off */
80228ffeebbSFabien Dessenne node->ins = BLT_INS_S1_OFF | BLT_INS_S3_MEM;
80328ffeebbSFabien Dessenne if (t_plan == BDISP_Y)
80428ffeebbSFabien Dessenne node->ins |= BLT_INS_S2_CF;
80528ffeebbSFabien Dessenne else
80628ffeebbSFabien Dessenne node->ins |= BLT_INS_S2_MEM;
80728ffeebbSFabien Dessenne break;
80828ffeebbSFabien Dessenne case 3:
80928ffeebbSFabien Dessenne default:
81028ffeebbSFabien Dessenne /* Src3 = Y
81128ffeebbSFabien Dessenne * Src2 = Cb or ColorFill if writing the Y plane
81228ffeebbSFabien Dessenne * Src1 = Cr or ColorFill if writing the Y plane */
81328ffeebbSFabien Dessenne node->ins = BLT_INS_S3_MEM;
81428ffeebbSFabien Dessenne if (t_plan == BDISP_Y)
81528ffeebbSFabien Dessenne node->ins |= BLT_INS_S2_CF | BLT_INS_S1_CF;
81628ffeebbSFabien Dessenne else
81728ffeebbSFabien Dessenne node->ins |= BLT_INS_S2_MEM | BLT_INS_S1_MEM;
81828ffeebbSFabien Dessenne break;
81928ffeebbSFabien Dessenne }
82028ffeebbSFabien Dessenne
82128ffeebbSFabien Dessenne /* Color convert */
82228ffeebbSFabien Dessenne node->ins |= cfg->cconv ? BLT_INS_IVMX : 0;
82328ffeebbSFabien Dessenne /* Scale needed if scaling OR 4:2:0 up/downsampling */
82428ffeebbSFabien Dessenne node->ins |= (cfg->scale || cfg->src_420 || cfg->dst_420) ?
82528ffeebbSFabien Dessenne BLT_INS_SCALE : 0;
82628ffeebbSFabien Dessenne
82728ffeebbSFabien Dessenne /* Target */
82828ffeebbSFabien Dessenne node->tba = (t_plan == BDISP_CBCR) ? dst->paddr[1] : dst->paddr[0];
82928ffeebbSFabien Dessenne
83028ffeebbSFabien Dessenne node->tty = dst->bytesperline;
83128ffeebbSFabien Dessenne node->tty |= bdisp_hw_color_format(dst_fmt);
83228ffeebbSFabien Dessenne node->tty |= BLT_TTY_DITHER;
83328ffeebbSFabien Dessenne node->tty |= (t_plan == BDISP_CBCR) ? BLT_TTY_CHROMA : 0;
83428ffeebbSFabien Dessenne node->tty |= cfg->hflip ? BLT_TTY_HSO : 0;
83528ffeebbSFabien Dessenne node->tty |= cfg->vflip ? BLT_TTY_VSO : 0;
83628ffeebbSFabien Dessenne
83728ffeebbSFabien Dessenne if (cfg->dst_420 && (t_plan == BDISP_CBCR)) {
83828ffeebbSFabien Dessenne /* 420 chroma downsampling */
83928ffeebbSFabien Dessenne dst_rect.height /= 2;
84028ffeebbSFabien Dessenne dst_rect.width /= 2;
84128ffeebbSFabien Dessenne dst_rect.left /= 2;
84228ffeebbSFabien Dessenne dst_rect.top /= 2;
84328ffeebbSFabien Dessenne dst_x_offset /= 2;
84428ffeebbSFabien Dessenne dst_width /= 2;
84528ffeebbSFabien Dessenne }
84628ffeebbSFabien Dessenne
84728ffeebbSFabien Dessenne node->txy = cfg->vflip ? (dst_rect.height - 1) : dst_rect.top;
84828ffeebbSFabien Dessenne node->txy <<= 16;
84928ffeebbSFabien Dessenne node->txy |= cfg->hflip ? (dst_width - dst_x_offset - 1) :
85028ffeebbSFabien Dessenne dst_rect.left;
85128ffeebbSFabien Dessenne
85228ffeebbSFabien Dessenne node->tsz = dst_rect.height << 16 | dst_rect.width;
85328ffeebbSFabien Dessenne
85428ffeebbSFabien Dessenne if (cfg->src_interlaced) {
85528ffeebbSFabien Dessenne /* handle only the top field which is half height of a frame */
85628ffeebbSFabien Dessenne src_rect.top /= 2;
85728ffeebbSFabien Dessenne src_rect.height /= 2;
85828ffeebbSFabien Dessenne }
85928ffeebbSFabien Dessenne
86028ffeebbSFabien Dessenne if (cfg->src_nbp == 1) {
86128ffeebbSFabien Dessenne /* Src 2 : RGB */
86228ffeebbSFabien Dessenne node->s2ba = src->paddr[0];
86328ffeebbSFabien Dessenne
86428ffeebbSFabien Dessenne node->s2ty = src->bytesperline;
86528ffeebbSFabien Dessenne if (cfg->src_interlaced)
86628ffeebbSFabien Dessenne node->s2ty *= 2;
86728ffeebbSFabien Dessenne
86828ffeebbSFabien Dessenne node->s2ty |= bdisp_hw_color_format(src_fmt);
86928ffeebbSFabien Dessenne
87028ffeebbSFabien Dessenne node->s2xy = src_rect.top << 16 | src_rect.left;
87128ffeebbSFabien Dessenne node->s2sz = src_rect.height << 16 | src_rect.width;
87228ffeebbSFabien Dessenne } else {
87328ffeebbSFabien Dessenne /* Src 2 : Cb or CbCr */
87428ffeebbSFabien Dessenne if (cfg->src_420) {
87528ffeebbSFabien Dessenne /* 420 chroma upsampling */
87628ffeebbSFabien Dessenne src_rect.top /= 2;
87728ffeebbSFabien Dessenne src_rect.left /= 2;
87828ffeebbSFabien Dessenne src_rect.width /= 2;
87928ffeebbSFabien Dessenne src_rect.height /= 2;
88028ffeebbSFabien Dessenne }
88128ffeebbSFabien Dessenne
88228ffeebbSFabien Dessenne node->s2ba = src->paddr[1];
88328ffeebbSFabien Dessenne
88428ffeebbSFabien Dessenne node->s2ty = src->bytesperline;
88528ffeebbSFabien Dessenne if (cfg->src_nbp == 3)
88628ffeebbSFabien Dessenne node->s2ty /= 2;
88728ffeebbSFabien Dessenne if (cfg->src_interlaced)
88828ffeebbSFabien Dessenne node->s2ty *= 2;
88928ffeebbSFabien Dessenne
89028ffeebbSFabien Dessenne node->s2ty |= bdisp_hw_color_format(src_fmt);
89128ffeebbSFabien Dessenne
89228ffeebbSFabien Dessenne node->s2xy = src_rect.top << 16 | src_rect.left;
89328ffeebbSFabien Dessenne node->s2sz = src_rect.height << 16 | src_rect.width;
89428ffeebbSFabien Dessenne
89528ffeebbSFabien Dessenne if (cfg->src_nbp == 3) {
89628ffeebbSFabien Dessenne /* Src 1 : Cr */
89728ffeebbSFabien Dessenne node->s1ba = src->paddr[2];
89828ffeebbSFabien Dessenne
89928ffeebbSFabien Dessenne node->s1ty = node->s2ty;
90028ffeebbSFabien Dessenne node->s1xy = node->s2xy;
90128ffeebbSFabien Dessenne }
90228ffeebbSFabien Dessenne
90328ffeebbSFabien Dessenne /* Src 3 : Y */
90428ffeebbSFabien Dessenne node->s3ba = src->paddr[0];
90528ffeebbSFabien Dessenne
90628ffeebbSFabien Dessenne node->s3ty = src->bytesperline;
90728ffeebbSFabien Dessenne if (cfg->src_interlaced)
90828ffeebbSFabien Dessenne node->s3ty *= 2;
90928ffeebbSFabien Dessenne node->s3ty |= bdisp_hw_color_format(src_fmt);
91028ffeebbSFabien Dessenne
91128ffeebbSFabien Dessenne if ((t_plan != BDISP_CBCR) && cfg->src_420) {
91228ffeebbSFabien Dessenne /* No chroma upsampling for output RGB / Y plane */
91328ffeebbSFabien Dessenne node->s3xy = node->s2xy * 2;
91428ffeebbSFabien Dessenne node->s3sz = node->s2sz * 2;
91528ffeebbSFabien Dessenne } else {
91628ffeebbSFabien Dessenne /* No need to read Y (Src3) when writing Chroma */
91728ffeebbSFabien Dessenne node->s3ty |= BLT_S3TY_BLANK_ACC;
91828ffeebbSFabien Dessenne node->s3xy = node->s2xy;
91928ffeebbSFabien Dessenne node->s3sz = node->s2sz;
92028ffeebbSFabien Dessenne }
92128ffeebbSFabien Dessenne }
92228ffeebbSFabien Dessenne
92328ffeebbSFabien Dessenne /* Resize (scale OR 4:2:0: chroma up/downsampling) */
92428ffeebbSFabien Dessenne if (node->ins & BLT_INS_SCALE) {
92528ffeebbSFabien Dessenne /* no need to compute Y when writing CbCr from RGB input */
92628ffeebbSFabien Dessenne bool skip_y = (t_plan == BDISP_CBCR) && !cfg->src_yuv;
92728ffeebbSFabien Dessenne
92828ffeebbSFabien Dessenne /* FCTL */
92928ffeebbSFabien Dessenne if (cfg->scale) {
93028ffeebbSFabien Dessenne node->fctl = BLT_FCTL_HV_SCALE;
93128ffeebbSFabien Dessenne if (!skip_y)
93228ffeebbSFabien Dessenne node->fctl |= BLT_FCTL_Y_HV_SCALE;
93328ffeebbSFabien Dessenne } else {
93428ffeebbSFabien Dessenne node->fctl = BLT_FCTL_HV_SAMPLE;
93528ffeebbSFabien Dessenne if (!skip_y)
93628ffeebbSFabien Dessenne node->fctl |= BLT_FCTL_Y_HV_SAMPLE;
93728ffeebbSFabien Dessenne }
93828ffeebbSFabien Dessenne
93928ffeebbSFabien Dessenne /* RSF - Chroma may need to be up/downsampled */
94028ffeebbSFabien Dessenne h_inc = cfg->h_inc;
94128ffeebbSFabien Dessenne v_inc = cfg->v_inc;
94228ffeebbSFabien Dessenne if (!cfg->src_420 && cfg->dst_420 && (t_plan == BDISP_CBCR)) {
94328ffeebbSFabien Dessenne /* RGB to 4:2:0 for Chroma: downsample */
94428ffeebbSFabien Dessenne h_inc *= 2;
94528ffeebbSFabien Dessenne v_inc *= 2;
94628ffeebbSFabien Dessenne } else if (cfg->src_420 && !cfg->dst_420) {
94728ffeebbSFabien Dessenne /* 4:2:0: to RGB: upsample*/
94828ffeebbSFabien Dessenne h_inc /= 2;
94928ffeebbSFabien Dessenne v_inc /= 2;
95028ffeebbSFabien Dessenne }
95128ffeebbSFabien Dessenne node->rsf = v_inc << 16 | h_inc;
95228ffeebbSFabien Dessenne
95328ffeebbSFabien Dessenne /* RZI */
95428ffeebbSFabien Dessenne node->rzi = BLT_RZI_DEFAULT;
95528ffeebbSFabien Dessenne
95628ffeebbSFabien Dessenne /* Filter table physical addr */
95728ffeebbSFabien Dessenne node->hfp = bdisp_hw_get_hf_addr(h_inc);
95828ffeebbSFabien Dessenne node->vfp = bdisp_hw_get_vf_addr(v_inc);
95928ffeebbSFabien Dessenne
96028ffeebbSFabien Dessenne /* Y version */
96128ffeebbSFabien Dessenne if (!skip_y) {
96228ffeebbSFabien Dessenne yh_inc = cfg->h_inc;
96328ffeebbSFabien Dessenne yv_inc = cfg->v_inc;
96428ffeebbSFabien Dessenne
96528ffeebbSFabien Dessenne node->y_rsf = yv_inc << 16 | yh_inc;
96628ffeebbSFabien Dessenne node->y_rzi = BLT_RZI_DEFAULT;
96728ffeebbSFabien Dessenne node->y_hfp = bdisp_hw_get_hf_addr(yh_inc);
96828ffeebbSFabien Dessenne node->y_vfp = bdisp_hw_get_vf_addr(yv_inc);
96928ffeebbSFabien Dessenne }
97028ffeebbSFabien Dessenne }
97128ffeebbSFabien Dessenne
97228ffeebbSFabien Dessenne /* Versatile matrix for RGB / YUV conversion */
97328ffeebbSFabien Dessenne if (cfg->cconv) {
97428ffeebbSFabien Dessenne ivmx = cfg->src_yuv ? bdisp_yuv_to_rgb : bdisp_rgb_to_yuv;
97528ffeebbSFabien Dessenne
97628ffeebbSFabien Dessenne node->ivmx0 = ivmx[0];
97728ffeebbSFabien Dessenne node->ivmx1 = ivmx[1];
97828ffeebbSFabien Dessenne node->ivmx2 = ivmx[2];
97928ffeebbSFabien Dessenne node->ivmx3 = ivmx[3];
98028ffeebbSFabien Dessenne }
98128ffeebbSFabien Dessenne }
98228ffeebbSFabien Dessenne
98328ffeebbSFabien Dessenne /**
98428ffeebbSFabien Dessenne * bdisp_hw_build_all_nodes
98528ffeebbSFabien Dessenne * @ctx: device context
98628ffeebbSFabien Dessenne *
98728ffeebbSFabien Dessenne * Build all the nodes for the blitter operation
98828ffeebbSFabien Dessenne *
98928ffeebbSFabien Dessenne * RETURNS:
99028ffeebbSFabien Dessenne * 0 on success
99128ffeebbSFabien Dessenne */
bdisp_hw_build_all_nodes(struct bdisp_ctx * ctx)99228ffeebbSFabien Dessenne static int bdisp_hw_build_all_nodes(struct bdisp_ctx *ctx)
99328ffeebbSFabien Dessenne {
99428ffeebbSFabien Dessenne struct bdisp_op_cfg cfg;
99528ffeebbSFabien Dessenne unsigned int i, nid = 0;
99628ffeebbSFabien Dessenne int src_x_offset = 0;
99728ffeebbSFabien Dessenne
99828ffeebbSFabien Dessenne for (i = 0; i < MAX_NB_NODE; i++)
99928ffeebbSFabien Dessenne if (!ctx->node[i]) {
100028ffeebbSFabien Dessenne dev_err(ctx->bdisp_dev->dev, "node %d is null\n", i);
100128ffeebbSFabien Dessenne return -EINVAL;
100228ffeebbSFabien Dessenne }
100328ffeebbSFabien Dessenne
100428ffeebbSFabien Dessenne /* Get configuration (scale, flip, ...) */
100528ffeebbSFabien Dessenne if (bdisp_hw_get_op_cfg(ctx, &cfg))
100628ffeebbSFabien Dessenne return -EINVAL;
100728ffeebbSFabien Dessenne
100828ffeebbSFabien Dessenne /* Split source in vertical strides (HW constraint) */
100928ffeebbSFabien Dessenne for (i = 0; i < MAX_VERTICAL_STRIDES; i++) {
101028ffeebbSFabien Dessenne /* Build RGB/Y node and link it to the previous node */
101128ffeebbSFabien Dessenne bdisp_hw_build_node(ctx, &cfg, ctx->node[nid],
101228ffeebbSFabien Dessenne cfg.dst_nbp == 1 ? BDISP_RGB : BDISP_Y,
101328ffeebbSFabien Dessenne src_x_offset);
101428ffeebbSFabien Dessenne if (nid)
101528ffeebbSFabien Dessenne ctx->node[nid - 1]->nip = ctx->node_paddr[nid];
101628ffeebbSFabien Dessenne nid++;
101728ffeebbSFabien Dessenne
101828ffeebbSFabien Dessenne /* Build additional Cb(Cr) node, link it to the previous one */
101928ffeebbSFabien Dessenne if (cfg.dst_nbp > 1) {
102028ffeebbSFabien Dessenne bdisp_hw_build_node(ctx, &cfg, ctx->node[nid],
102128ffeebbSFabien Dessenne BDISP_CBCR, src_x_offset);
102228ffeebbSFabien Dessenne ctx->node[nid - 1]->nip = ctx->node_paddr[nid];
102328ffeebbSFabien Dessenne nid++;
102428ffeebbSFabien Dessenne }
102528ffeebbSFabien Dessenne
102628ffeebbSFabien Dessenne /* Next stride until full width covered */
102728ffeebbSFabien Dessenne src_x_offset += MAX_SRC_WIDTH;
102828ffeebbSFabien Dessenne if (src_x_offset >= ctx->src.crop.width)
102928ffeebbSFabien Dessenne break;
103028ffeebbSFabien Dessenne }
103128ffeebbSFabien Dessenne
103228ffeebbSFabien Dessenne /* Mark last node as the last */
103328ffeebbSFabien Dessenne ctx->node[nid - 1]->nip = 0;
103428ffeebbSFabien Dessenne
103528ffeebbSFabien Dessenne return 0;
103628ffeebbSFabien Dessenne }
103728ffeebbSFabien Dessenne
103828ffeebbSFabien Dessenne /**
103934b6beb6SFabien Dessenne * bdisp_hw_save_request
104034b6beb6SFabien Dessenne * @ctx: device context
104134b6beb6SFabien Dessenne *
104234b6beb6SFabien Dessenne * Save a copy of the request and of the built nodes
104334b6beb6SFabien Dessenne *
104434b6beb6SFabien Dessenne * RETURNS:
104534b6beb6SFabien Dessenne * None
104634b6beb6SFabien Dessenne */
bdisp_hw_save_request(struct bdisp_ctx * ctx)104734b6beb6SFabien Dessenne static void bdisp_hw_save_request(struct bdisp_ctx *ctx)
104834b6beb6SFabien Dessenne {
104934b6beb6SFabien Dessenne struct bdisp_node **copy_node = ctx->bdisp_dev->dbg.copy_node;
105034b6beb6SFabien Dessenne struct bdisp_request *request = &ctx->bdisp_dev->dbg.copy_request;
105134b6beb6SFabien Dessenne struct bdisp_node **node = ctx->node;
105234b6beb6SFabien Dessenne int i;
105334b6beb6SFabien Dessenne
105434b6beb6SFabien Dessenne /* Request copy */
105534b6beb6SFabien Dessenne request->src = ctx->src;
105634b6beb6SFabien Dessenne request->dst = ctx->dst;
105734b6beb6SFabien Dessenne request->hflip = ctx->hflip;
105834b6beb6SFabien Dessenne request->vflip = ctx->vflip;
105934b6beb6SFabien Dessenne request->nb_req++;
106034b6beb6SFabien Dessenne
106134b6beb6SFabien Dessenne /* Nodes copy */
106234b6beb6SFabien Dessenne for (i = 0; i < MAX_NB_NODE; i++) {
106334b6beb6SFabien Dessenne /* Allocate memory if not done yet */
106434b6beb6SFabien Dessenne if (!copy_node[i]) {
106534b6beb6SFabien Dessenne copy_node[i] = devm_kzalloc(ctx->bdisp_dev->dev,
1066bde2b96dSFabien Dessenne sizeof(*copy_node[i]),
1067df8ab4c6SJia-Ju Bai GFP_ATOMIC);
106834b6beb6SFabien Dessenne if (!copy_node[i])
106934b6beb6SFabien Dessenne return;
107034b6beb6SFabien Dessenne }
1071bde2b96dSFabien Dessenne *copy_node[i] = *node[i];
107234b6beb6SFabien Dessenne }
107334b6beb6SFabien Dessenne }
107434b6beb6SFabien Dessenne
107534b6beb6SFabien Dessenne /**
107628ffeebbSFabien Dessenne * bdisp_hw_update
107728ffeebbSFabien Dessenne * @ctx: device context
107828ffeebbSFabien Dessenne *
107928ffeebbSFabien Dessenne * Send the request to the HW
108028ffeebbSFabien Dessenne *
108128ffeebbSFabien Dessenne * RETURNS:
108228ffeebbSFabien Dessenne * 0 on success
108328ffeebbSFabien Dessenne */
bdisp_hw_update(struct bdisp_ctx * ctx)108428ffeebbSFabien Dessenne int bdisp_hw_update(struct bdisp_ctx *ctx)
108528ffeebbSFabien Dessenne {
108628ffeebbSFabien Dessenne int ret;
108728ffeebbSFabien Dessenne struct bdisp_dev *bdisp = ctx->bdisp_dev;
108828ffeebbSFabien Dessenne struct device *dev = bdisp->dev;
108928ffeebbSFabien Dessenne unsigned int node_id;
109028ffeebbSFabien Dessenne
109128ffeebbSFabien Dessenne dev_dbg(dev, "%s\n", __func__);
109228ffeebbSFabien Dessenne
109328ffeebbSFabien Dessenne /* build nodes */
109428ffeebbSFabien Dessenne ret = bdisp_hw_build_all_nodes(ctx);
109528ffeebbSFabien Dessenne if (ret) {
109628ffeebbSFabien Dessenne dev_err(dev, "cannot build nodes (%d)\n", ret);
109728ffeebbSFabien Dessenne return ret;
109828ffeebbSFabien Dessenne }
109928ffeebbSFabien Dessenne
110034b6beb6SFabien Dessenne /* Save a copy of the request */
110134b6beb6SFabien Dessenne bdisp_hw_save_request(ctx);
110234b6beb6SFabien Dessenne
110328ffeebbSFabien Dessenne /* Configure interrupt to 'Last Node Reached for AQ1' */
110428ffeebbSFabien Dessenne writel(BLT_AQ1_CTL_CFG, bdisp->regs + BLT_AQ1_CTL);
110528ffeebbSFabien Dessenne writel(BLT_ITS_AQ1_LNA, bdisp->regs + BLT_ITM0);
110628ffeebbSFabien Dessenne
110728ffeebbSFabien Dessenne /* Write first node addr */
110828ffeebbSFabien Dessenne writel(ctx->node_paddr[0], bdisp->regs + BLT_AQ1_IP);
110928ffeebbSFabien Dessenne
111028ffeebbSFabien Dessenne /* Find and write last node addr : this starts the HW processing */
111128ffeebbSFabien Dessenne for (node_id = 0; node_id < MAX_NB_NODE - 1; node_id++) {
111228ffeebbSFabien Dessenne if (!ctx->node[node_id]->nip)
111328ffeebbSFabien Dessenne break;
111428ffeebbSFabien Dessenne }
111528ffeebbSFabien Dessenne writel(ctx->node_paddr[node_id], bdisp->regs + BLT_AQ1_LNA);
111628ffeebbSFabien Dessenne
111728ffeebbSFabien Dessenne return 0;
111828ffeebbSFabien Dessenne }
1119