aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/sun4i/sun4i_frontend.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun4i_frontend.c')
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_frontend.c113
1 files changed, 90 insertions, 23 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c
index ddf6cfa6dd23..1a7ebc45747e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_frontend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c
@@ -107,8 +107,34 @@ EXPORT_SYMBOL(sun4i_frontend_update_buffer);
107static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val) 107static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val)
108{ 108{
109 switch (fmt) { 109 switch (fmt) {
110 case DRM_FORMAT_ARGB8888: 110 case DRM_FORMAT_XRGB8888:
111 *val = 5; 111 *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB;
112 return 0;
113
114 default:
115 return -EINVAL;
116 }
117}
118
119static int sun4i_frontend_drm_format_to_input_mode(uint32_t fmt, u32 *val)
120{
121 if (drm_format_num_planes(fmt) == 1)
122 *val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED;
123 else
124 return -EINVAL;
125
126 return 0;
127}
128
129static int sun4i_frontend_drm_format_to_input_sequence(uint32_t fmt, u32 *val)
130{
131 switch (fmt) {
132 case DRM_FORMAT_BGRX8888:
133 *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX;
134 return 0;
135
136 case DRM_FORMAT_XRGB8888:
137 *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB;
112 return 0; 138 return 0;
113 139
114 default: 140 default:
@@ -119,9 +145,12 @@ static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val)
119static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val) 145static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val)
120{ 146{
121 switch (fmt) { 147 switch (fmt) {
148 case DRM_FORMAT_BGRX8888:
149 *val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888;
150 return 0;
151
122 case DRM_FORMAT_XRGB8888: 152 case DRM_FORMAT_XRGB8888:
123 case DRM_FORMAT_ARGB8888: 153 *val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888;
124 *val = 2;
125 return 0; 154 return 0;
126 155
127 default: 156 default:
@@ -129,22 +158,54 @@ static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val)
129 } 158 }
130} 159}
131 160
161static const uint32_t sun4i_frontend_formats[] = {
162 DRM_FORMAT_BGRX8888,
163 DRM_FORMAT_XRGB8888,
164};
165
166bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier)
167{
168 unsigned int i;
169
170 if (modifier != DRM_FORMAT_MOD_LINEAR)
171 return false;
172
173 for (i = 0; i < ARRAY_SIZE(sun4i_frontend_formats); i++)
174 if (sun4i_frontend_formats[i] == fmt)
175 return true;
176
177 return false;
178}
179EXPORT_SYMBOL(sun4i_frontend_format_is_supported);
180
132int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, 181int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
133 struct drm_plane *plane, uint32_t out_fmt) 182 struct drm_plane *plane, uint32_t out_fmt)
134{ 183{
135 struct drm_plane_state *state = plane->state; 184 struct drm_plane_state *state = plane->state;
136 struct drm_framebuffer *fb = state->fb; 185 struct drm_framebuffer *fb = state->fb;
186 uint32_t format = fb->format->format;
137 u32 out_fmt_val; 187 u32 out_fmt_val;
138 u32 in_fmt_val; 188 u32 in_fmt_val, in_mod_val, in_ps_val;
139 int ret; 189 int ret;
140 190
141 ret = sun4i_frontend_drm_format_to_input_fmt(fb->format->format, 191 ret = sun4i_frontend_drm_format_to_input_fmt(format, &in_fmt_val);
142 &in_fmt_val);
143 if (ret) { 192 if (ret) {
144 DRM_DEBUG_DRIVER("Invalid input format\n"); 193 DRM_DEBUG_DRIVER("Invalid input format\n");
145 return ret; 194 return ret;
146 } 195 }
147 196
197 ret = sun4i_frontend_drm_format_to_input_mode(format, &in_mod_val);
198 if (ret) {
199 DRM_DEBUG_DRIVER("Invalid input mode\n");
200 return ret;
201 }
202
203 ret = sun4i_frontend_drm_format_to_input_sequence(format, &in_ps_val);
204 if (ret) {
205 DRM_DEBUG_DRIVER("Invalid pixel sequence\n");
206 return ret;
207 }
208
148 ret = sun4i_frontend_drm_format_to_output_fmt(out_fmt, &out_fmt_val); 209 ret = sun4i_frontend_drm_format_to_output_fmt(out_fmt, &out_fmt_val);
149 if (ret) { 210 if (ret) {
150 DRM_DEBUG_DRIVER("Invalid output format\n"); 211 DRM_DEBUG_DRIVER("Invalid output format\n");
@@ -162,10 +223,12 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
162 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400); 223 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400);
163 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400); 224 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400);
164 225
226 regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG,
227 SUN4I_FRONTEND_BYPASS_CSC_EN,
228 SUN4I_FRONTEND_BYPASS_CSC_EN);
229
165 regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG, 230 regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG,
166 SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(1) | 231 in_mod_val | in_fmt_val | in_ps_val);
167 SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(in_fmt_val) |
168 SUN4I_FRONTEND_INPUT_FMT_PS(1));
169 232
170 /* 233 /*
171 * TODO: It look like the A31 and A80 at least will need the 234 * TODO: It look like the A31 and A80 at least will need the
@@ -173,7 +236,7 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
173 * ARGB8888). 236 * ARGB8888).
174 */ 237 */
175 regmap_write(frontend->regs, SUN4I_FRONTEND_OUTPUT_FMT_REG, 238 regmap_write(frontend->regs, SUN4I_FRONTEND_OUTPUT_FMT_REG,
176 SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(out_fmt_val)); 239 out_fmt_val);
177 240
178 return 0; 241 return 0;
179} 242}
@@ -183,16 +246,24 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
183 struct drm_plane *plane) 246 struct drm_plane *plane)
184{ 247{
185 struct drm_plane_state *state = plane->state; 248 struct drm_plane_state *state = plane->state;
249 struct drm_framebuffer *fb = state->fb;
250 uint32_t luma_width, luma_height;
251 uint32_t chroma_width, chroma_height;
186 252
187 /* Set height and width */ 253 /* Set height and width */
188 DRM_DEBUG_DRIVER("Frontend size W: %u H: %u\n", 254 DRM_DEBUG_DRIVER("Frontend size W: %u H: %u\n",
189 state->crtc_w, state->crtc_h); 255 state->crtc_w, state->crtc_h);
256
257 luma_width = state->src_w >> 16;
258 luma_height = state->src_h >> 16;
259
260 chroma_width = DIV_ROUND_UP(luma_width, fb->format->hsub);
261 chroma_height = DIV_ROUND_UP(luma_height, fb->format->vsub);
262
190 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_INSIZE_REG, 263 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_INSIZE_REG,
191 SUN4I_FRONTEND_INSIZE(state->src_h >> 16, 264 SUN4I_FRONTEND_INSIZE(luma_height, luma_width));
192 state->src_w >> 16));
193 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_INSIZE_REG, 265 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_INSIZE_REG,
194 SUN4I_FRONTEND_INSIZE(state->src_h >> 16, 266 SUN4I_FRONTEND_INSIZE(chroma_height, chroma_width));
195 state->src_w >> 16));
196 267
197 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_OUTSIZE_REG, 268 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_OUTSIZE_REG,
198 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w)); 269 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w));
@@ -200,14 +271,14 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
200 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w)); 271 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w));
201 272
202 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZFACT_REG, 273 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZFACT_REG,
203 state->src_w / state->crtc_w); 274 (luma_width << 16) / state->crtc_w);
204 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZFACT_REG, 275 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZFACT_REG,
205 state->src_w / state->crtc_w); 276 (chroma_width << 16) / state->crtc_w);
206 277
207 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTFACT_REG, 278 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTFACT_REG,
208 state->src_h / state->crtc_h); 279 (luma_height << 16) / state->crtc_h);
209 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTFACT_REG, 280 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTFACT_REG,
210 state->src_h / state->crtc_h); 281 (chroma_height << 16) / state->crtc_h);
211 282
212 regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG, 283 regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG,
213 SUN4I_FRONTEND_FRM_CTRL_REG_RDY, 284 SUN4I_FRONTEND_FRM_CTRL_REG_RDY,
@@ -339,10 +410,6 @@ static int sun4i_frontend_runtime_resume(struct device *dev)
339 SUN4I_FRONTEND_EN_EN, 410 SUN4I_FRONTEND_EN_EN,
340 SUN4I_FRONTEND_EN_EN); 411 SUN4I_FRONTEND_EN_EN);
341 412
342 regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG,
343 SUN4I_FRONTEND_BYPASS_CSC_EN,
344 SUN4I_FRONTEND_BYPASS_CSC_EN);
345
346 sun4i_frontend_scaler_init(frontend); 413 sun4i_frontend_scaler_init(frontend);
347 414
348 return 0; 415 return 0;