Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 1 | // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 2 | /* |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 3 | * Copyright (c) 2019 Amlogic, Inc. All rights reserved. |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 4 | */ |
| 5 | |
| 6 | #include "ionvideo.h" |
| 7 | |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 8 | #define IONVIDEO_CANVAS_COUNT 5 |
| 9 | int ionvideo_canvas_id[IONVIDEO_CANVAS_COUNT] = {-1, -1, -1, -1, -1}; |
| 10 | |
| 11 | void ionvideo_alloc_canvas(void) |
| 12 | { |
| 13 | const char *owner = "ionvideo"; |
| 14 | int i; |
| 15 | |
| 16 | if (ionvideo_canvas_id[0] != -1 && |
| 17 | ionvideo_canvas_id[1] != -1 && |
| 18 | ionvideo_canvas_id[2] != -1 && |
| 19 | ionvideo_canvas_id[3] != -1 && |
| 20 | ionvideo_canvas_id[4] != -1) |
| 21 | return; |
| 22 | |
| 23 | for (i = 0; i < IONVIDEO_CANVAS_COUNT; i++) { |
| 24 | if (ionvideo_canvas_id[i] == -1) |
| 25 | ionvideo_canvas_id[i] = |
| 26 | canvas_pool_map_alloc_canvas(owner); |
| 27 | } |
| 28 | |
| 29 | for (i = 0; i < IONVIDEO_CANVAS_COUNT; i++) { |
| 30 | if (ionvideo_canvas_id[i] == -1) { |
| 31 | pr_err("%s: %x, %x, %x, %x, %x\n", |
| 32 | __func__, |
| 33 | ionvideo_canvas_id[0], |
| 34 | ionvideo_canvas_id[1], |
| 35 | ionvideo_canvas_id[2], |
| 36 | ionvideo_canvas_id[3], |
| 37 | ionvideo_canvas_id[4]); |
| 38 | break; |
| 39 | } |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | void ionvideo_free_canvas(void) |
| 44 | { |
| 45 | int i; |
| 46 | |
| 47 | for (i = 0; i < IONVIDEO_CANVAS_COUNT; i++) { |
| 48 | if (ionvideo_canvas_id[i] != -1) { |
| 49 | canvas_pool_map_free_canvas(ionvideo_canvas_id[i]); |
| 50 | ionvideo_canvas_id[i] = -1; |
| 51 | } |
| 52 | } |
| 53 | } |
| 54 | |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 55 | static inline void paint_mode_convert(int paint_mode, int *src_position, |
| 56 | int *dst_paint_position, |
| 57 | int *dst_plane_position) |
| 58 | { |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 59 | if (paint_mode == 0) { /* stretch full */ |
| 60 | dst_paint_position[0] = dst_plane_position[0]; |
| 61 | dst_paint_position[1] = dst_plane_position[1]; |
| 62 | dst_paint_position[2] = dst_plane_position[2]; |
| 63 | dst_paint_position[3] = dst_plane_position[3]; |
| 64 | } else if (paint_mode == 1) { /* keep size */ |
| 65 | dst_paint_position[0] = |
| 66 | (dst_plane_position[2] - src_position[2]) >> 1; |
| 67 | dst_paint_position[1] = |
| 68 | (dst_plane_position[3] - src_position[3]) >> 1; |
| 69 | dst_paint_position[2] = src_position[2]; |
| 70 | dst_paint_position[3] = src_position[3]; |
| 71 | } else if (paint_mode == 2) { |
| 72 | int dw = 0, dh = 0; |
| 73 | |
| 74 | if (src_position[2] * dst_plane_position[3] >= |
| 75 | dst_plane_position[2] |
| 76 | * src_position[3]) { /* crop full */ |
| 77 | dh = dst_plane_position[3]; |
| 78 | dw = dh * src_position[2] / src_position[3]; |
| 79 | } else { |
| 80 | dw = dst_plane_position[2]; |
| 81 | dh = dw * src_position[3] / src_position[2]; |
| 82 | } |
| 83 | dst_paint_position[0] = (dst_plane_position[2] - dw) >> 1; |
| 84 | dst_paint_position[1] = (dst_plane_position[3] - dh) >> 1; |
| 85 | dst_paint_position[2] = dw; |
| 86 | dst_paint_position[3] = dh; |
| 87 | } else if (paint_mode == 3) { /* keep ration black */ |
| 88 | int dw = 0, dh = 0; |
| 89 | |
| 90 | if (src_position[2] * dst_plane_position[3] >= |
| 91 | dst_plane_position[2] * src_position[3]) { |
| 92 | dw = dst_plane_position[2]; |
| 93 | dh = dw * src_position[3] / src_position[2]; |
| 94 | } else { |
| 95 | dh = dst_plane_position[3]; |
| 96 | dw = dh * src_position[2] / src_position[3]; |
| 97 | } |
| 98 | dst_paint_position[0] = (dst_plane_position[2] - dw) >> 1; |
| 99 | dst_paint_position[1] = (dst_plane_position[3] - dh) >> 1; |
| 100 | dst_paint_position[2] = dw; |
| 101 | dst_paint_position[3] = dh; |
| 102 | } else if (paint_mode == 4) { |
| 103 | ; |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | static int get_input_format(struct vframe_s *vf) |
| 108 | { |
| 109 | int format = GE2D_FORMAT_M24_NV21; |
| 110 | |
| 111 | if (vf->type & VIDTYPE_VIU_422) { |
| 112 | if ((vf->type & 3) == VIDTYPE_INTERLACE_BOTTOM) { |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 113 | format = GE2D_FORMAT_S16_YUV422 | |
| 114 | (GE2D_FORMAT_S16_YUV422B & (3 << 3)); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 115 | } else if ((vf->type & 3) == VIDTYPE_INTERLACE_TOP) { |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 116 | format = GE2D_FORMAT_S16_YUV422 | |
| 117 | (GE2D_FORMAT_S16_YUV422T & (3 << 3)); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 118 | } else { |
| 119 | format = GE2D_FORMAT_S16_YUV422; |
| 120 | } |
| 121 | |
| 122 | if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL) { |
| 123 | if ((vf->bitdepth & BITDEPTH_Y10) && |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 124 | (vf->bitdepth & FULL_PACK_422_MODE)) |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 125 | format = GE2D_FORMAT_S16_10BIT_YUV422; |
| 126 | } |
| 127 | } else if (vf->type & VIDTYPE_VIU_NV21) { |
| 128 | if ((vf->type & 3) == VIDTYPE_INTERLACE_BOTTOM) { |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 129 | format = GE2D_FORMAT_M24_NV21 | |
| 130 | (GE2D_FORMAT_M24_NV21B & (3 << 3)); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 131 | } else if ((vf->type & 3) == VIDTYPE_INTERLACE_TOP) { |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 132 | format = GE2D_FORMAT_M24_NV21 | |
| 133 | (GE2D_FORMAT_M24_NV21T & (3 << 3)); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 134 | } else { |
| 135 | format = GE2D_FORMAT_M24_NV21; |
| 136 | } |
| 137 | } else { |
| 138 | if ((vf->type & 3) == VIDTYPE_INTERLACE_BOTTOM) { |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 139 | format = GE2D_FORMAT_M24_YUV420 | |
| 140 | (GE2D_FMT_M24_YUV420B & (3 << 3)); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 141 | } else if ((vf->type & 3) == VIDTYPE_INTERLACE_TOP) { |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 142 | format = GE2D_FORMAT_M24_YUV420 | |
| 143 | (GE2D_FORMAT_M24_YUV420T & (3 << 3)); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 144 | } else { |
| 145 | format = GE2D_FORMAT_M24_YUV420; |
| 146 | } |
| 147 | } |
| 148 | return format; |
| 149 | } |
| 150 | |
| 151 | static inline void ge2d_src_config(struct vframe_s *vf, |
| 152 | struct config_para_ex_s *ge2d_config) |
| 153 | { |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 154 | int canvas_id = -1; |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 155 | struct canvas_s src_cs0, src_cs1, src_cs2; |
| 156 | |
| 157 | if (vf->canvas0Addr == (u32)-1) { |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 158 | canvas_config_config(ionvideo_canvas_id[2], |
| 159 | &vf->canvas0_config[0]); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 160 | |
| 161 | if (vf->plane_num > 1) |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 162 | canvas_config_config(ionvideo_canvas_id[3], |
| 163 | &vf->canvas0_config[1]); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 164 | |
| 165 | if (vf->plane_num > 2) |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 166 | canvas_config_config(ionvideo_canvas_id[4], |
| 167 | &vf->canvas0_config[2]); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 168 | |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 169 | canvas_id = |
| 170 | ionvideo_canvas_id[2] |
| 171 | | (ionvideo_canvas_id[3] << 8) |
| 172 | | (ionvideo_canvas_id[4] << 16); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 173 | |
| 174 | ge2d_config->src_planes[0].addr = |
| 175 | vf->canvas0_config[0].phy_addr; |
| 176 | ge2d_config->src_planes[0].w = |
| 177 | vf->canvas0_config[0].width; |
| 178 | ge2d_config->src_planes[0].h = |
| 179 | vf->canvas0_config[0].height; |
| 180 | ge2d_config->src_planes[1].addr = |
| 181 | vf->canvas0_config[1].phy_addr; |
| 182 | ge2d_config->src_planes[1].w = |
| 183 | vf->canvas0_config[1].width; |
| 184 | ge2d_config->src_planes[1].h = |
| 185 | vf->canvas0_config[1].height << 1; |
| 186 | |
| 187 | if (vf->plane_num == 3) { |
| 188 | ge2d_config->src_planes[2].addr = |
| 189 | vf->canvas0_config[2].phy_addr; |
| 190 | ge2d_config->src_planes[2].w = |
| 191 | vf->canvas0_config[2].width; |
| 192 | ge2d_config->src_planes[2].h = |
| 193 | vf->canvas0_config[2].height << 1; |
| 194 | } |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 195 | ge2d_config->src_para.canvas_index = canvas_id; |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 196 | } else { |
| 197 | canvas_read(vf->canvas0Addr & 0xff, &src_cs0); |
| 198 | canvas_read(vf->canvas0Addr >> 8 & 0xff, &src_cs1); |
| 199 | canvas_read(vf->canvas0Addr >> 16 & 0xff, &src_cs2); |
| 200 | ge2d_config->src_planes[0].addr = src_cs0.addr; |
| 201 | ge2d_config->src_planes[0].w = src_cs0.width; |
| 202 | ge2d_config->src_planes[0].h = src_cs0.height; |
| 203 | ge2d_config->src_planes[1].addr = src_cs1.addr; |
| 204 | ge2d_config->src_planes[1].w = src_cs1.width; |
| 205 | ge2d_config->src_planes[1].h = src_cs1.height; |
| 206 | ge2d_config->src_planes[2].addr = src_cs2.addr; |
| 207 | ge2d_config->src_planes[2].w = src_cs2.width; |
| 208 | ge2d_config->src_planes[2].h = src_cs2.height; |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 209 | ge2d_config->src_para.canvas_index = vf->canvas0Addr; |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 210 | } |
| 211 | /* data operating. */ |
| 212 | ge2d_config->alu_const_color = 0; /* 0x000000ff; */ |
| 213 | ge2d_config->bitmask_en = 0; |
| 214 | ge2d_config->src1_gb_alpha = 0; /* 0xff; */ |
| 215 | |
| 216 | ge2d_config->src_key.key_enable = 0; |
| 217 | ge2d_config->src_key.key_mask = 0; |
| 218 | ge2d_config->src_key.key_mode = 0; |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 219 | ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; |
| 220 | ge2d_config->src_para.format = get_input_format(vf); |
| 221 | ge2d_config->src_para.fill_color_en = 0; |
| 222 | ge2d_config->src_para.fill_mode = 0; |
| 223 | ge2d_config->src_para.x_rev = 0; |
| 224 | ge2d_config->src_para.y_rev = 0; |
| 225 | ge2d_config->src_para.color = 0xffffffff; |
| 226 | ge2d_config->src_para.top = 0; |
| 227 | ge2d_config->src_para.left = 0; |
| 228 | ge2d_config->src_para.width = vf->width; |
| 229 | |
| 230 | if (vf->type & VIDTYPE_INTERLACE) |
| 231 | ge2d_config->src_para.height = vf->height >> 1; |
| 232 | else |
| 233 | ge2d_config->src_para.height = vf->height; |
| 234 | |
| 235 | ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID; |
| 236 | /* ppmgr2_printk(2, "vf_width is %d , vf_height is %d type:%p\n", |
| 237 | * vf->width, vf->height, (void *)vf->type); |
| 238 | */ |
| 239 | } |
| 240 | |
| 241 | static int ge2d_paint_dst(struct ge2d_context_s *context, |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 242 | struct config_para_ex_s *ge2d_config, |
| 243 | int dst_canvas_id, int dst_pixel_format, |
| 244 | int *src_position, int *dst_paint_position, |
| 245 | int *dst_plane_position) |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 246 | { |
| 247 | struct canvas_s dst_cd; |
| 248 | |
| 249 | ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID; |
| 250 | ge2d_config->dst_para.fill_color_en = 0; |
| 251 | ge2d_config->dst_para.fill_mode = 0; |
| 252 | ge2d_config->dst_para.color = 0; |
| 253 | ge2d_config->dst_para.top = dst_plane_position[0]; |
| 254 | ge2d_config->dst_para.left = dst_plane_position[1]; |
| 255 | ge2d_config->dst_para.width = dst_plane_position[2]; |
| 256 | ge2d_config->dst_para.height = dst_plane_position[3]; |
| 257 | |
| 258 | if (dst_pixel_format == GE2D_FORMAT_S8_Y) { |
| 259 | canvas_read(dst_canvas_id & 0xff, &dst_cd); |
| 260 | ge2d_config->dst_planes[0].addr = dst_cd.addr; |
| 261 | ge2d_config->dst_planes[0].w = dst_cd.width; |
| 262 | ge2d_config->dst_planes[0].h = dst_cd.height; |
| 263 | ge2d_config->dst_para.canvas_index = dst_canvas_id & 0xff; |
| 264 | ge2d_config->dst_para.format = dst_pixel_format |
| 265 | | GE2D_LITTLE_ENDIAN; |
| 266 | |
| 267 | if (ge2d_context_config_ex(context, ge2d_config) < 0) { |
| 268 | ppmgr2_printk(1, "Ge2d configing error.\n"); |
| 269 | return -1; |
| 270 | } |
| 271 | stretchblt_noalpha(context, src_position[0], src_position[1], |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 272 | src_position[2], src_position[3], |
| 273 | dst_paint_position[0], |
| 274 | dst_paint_position[1], |
| 275 | dst_paint_position[2], |
| 276 | dst_paint_position[3]); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 277 | canvas_read(dst_canvas_id >> 8 & 0xff, &dst_cd); |
| 278 | ge2d_config->dst_planes[0].addr = dst_cd.addr; |
| 279 | ge2d_config->dst_planes[0].w = dst_cd.width; |
| 280 | ge2d_config->dst_planes[0].h = dst_cd.height; |
| 281 | ge2d_config->dst_para.canvas_index = dst_canvas_id >> 8 & 0xff; |
| 282 | ge2d_config->dst_para.format = GE2D_FORMAT_S8_CB |
| 283 | | GE2D_LITTLE_ENDIAN; |
| 284 | ge2d_config->dst_para.width = dst_paint_position[2] >> 1; |
| 285 | ge2d_config->dst_para.height = dst_paint_position[3] >> 1; |
| 286 | |
| 287 | if (ge2d_context_config_ex(context, ge2d_config) < 0) { |
| 288 | ppmgr2_printk(1, "Ge2d configing error.\n"); |
| 289 | return -1; |
| 290 | } |
| 291 | stretchblt_noalpha(context, src_position[0], src_position[1], |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 292 | src_position[2], src_position[3], |
| 293 | dst_paint_position[0], |
| 294 | dst_paint_position[1], |
| 295 | dst_paint_position[2], |
| 296 | dst_paint_position[3]); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 297 | |
| 298 | canvas_read(dst_canvas_id >> 16 & 0xff, &dst_cd); |
| 299 | ge2d_config->dst_planes[0].addr = dst_cd.addr; |
| 300 | ge2d_config->dst_planes[0].w = dst_cd.width; |
| 301 | ge2d_config->dst_planes[0].h = dst_cd.height; |
| 302 | ge2d_config->dst_para.canvas_index = dst_canvas_id >> 16 & 0xff; |
| 303 | ge2d_config->dst_para.format = GE2D_FORMAT_S8_CR |
| 304 | | GE2D_LITTLE_ENDIAN; |
| 305 | |
| 306 | if (ge2d_context_config_ex(context, ge2d_config) < 0) { |
| 307 | ppmgr2_printk(1, "Ge2d configing error.\n"); |
| 308 | return -1; |
| 309 | } |
| 310 | stretchblt_noalpha(context, src_position[0], src_position[1], |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 311 | src_position[2], src_position[3], |
| 312 | dst_paint_position[0], |
| 313 | dst_paint_position[1], |
| 314 | dst_paint_position[2], |
| 315 | dst_paint_position[3]); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 316 | } else { |
| 317 | canvas_read(dst_canvas_id & 0xff, &dst_cd); |
| 318 | ge2d_config->dst_planes[0].addr = dst_cd.addr; |
| 319 | ge2d_config->dst_planes[0].w = dst_cd.width; |
| 320 | ge2d_config->dst_planes[0].h = dst_cd.height; |
| 321 | ge2d_config->dst_para.format = dst_pixel_format |
| 322 | | GE2D_LITTLE_ENDIAN; |
| 323 | ge2d_config->dst_para.canvas_index = dst_canvas_id; |
| 324 | |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 325 | if (dst_paint_position[2] > dst_cd.width || |
| 326 | dst_paint_position[3] > dst_cd.height) { |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 327 | pr_info("ppmgr2-dev: error: id %d,width %d,height %d, ", |
| 328 | dst_canvas_id, dst_cd.width, dst_cd.height); |
| 329 | pr_info("ppmgr2-dev: dst_width %d,dst_height %d\n", |
| 330 | dst_paint_position[2], dst_paint_position[3]); |
| 331 | ppmgr2_printk(1, "error case : dst addr:%p\n", |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 332 | (void *)dst_cd.addr); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 333 | return -1; |
| 334 | } |
| 335 | if (ge2d_context_config_ex(context, ge2d_config) < 0) { |
| 336 | ppmgr2_printk(1, "Ge2d configing error.\n"); |
| 337 | return -1; |
| 338 | } |
| 339 | stretchblt_noalpha(context, src_position[0], src_position[1], |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 340 | src_position[2], src_position[3], |
| 341 | dst_paint_position[0], |
| 342 | dst_paint_position[1], |
| 343 | dst_paint_position[2], |
| 344 | dst_paint_position[3]); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 345 | } |
| 346 | /* ppmgr2_printk(2, "dst addr:%p w:%d h:%d canvas_id:%p format:%p\n", |
| 347 | * (void *)dst_cd.addr, dst_cd.width, dst_cd.height, |
| 348 | * (void *)dst_canvas_id, |
| 349 | * (void *)ge2d_config->dst_para.format); |
| 350 | */ |
| 351 | ppmgr2_printk(2, "dst plane w:%d h:%d paint w:%d h:%d\n", |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 352 | dst_plane_position[2], dst_plane_position[3], |
| 353 | dst_paint_position[2], dst_paint_position[3]); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 354 | |
| 355 | return 0; |
| 356 | } |
| 357 | |
| 358 | static inline void ge2d_mirror_config(int dst_mirror, |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 359 | struct config_para_ex_s *ge2d_config) |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 360 | { |
| 361 | if (dst_mirror == 1) { |
| 362 | ge2d_config->dst_para.x_rev = 1; |
| 363 | ge2d_config->dst_para.y_rev = 0; |
| 364 | } else if (dst_mirror == 2) { |
| 365 | ge2d_config->dst_para.x_rev = 0; |
| 366 | ge2d_config->dst_para.y_rev = 1; |
| 367 | } else { |
| 368 | ge2d_config->dst_para.x_rev = 0; |
| 369 | ge2d_config->dst_para.y_rev = 0; |
| 370 | } |
| 371 | } |
| 372 | |
| 373 | static inline void ge2d_angle_config(int dst_angle, |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 374 | struct config_para_ex_s *ge2d_config) |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 375 | { |
| 376 | if (dst_angle == 1) { |
| 377 | ge2d_config->dst_xy_swap = 1; |
| 378 | ge2d_config->dst_para.x_rev ^= 1; |
| 379 | } else if (dst_angle == 2) { |
| 380 | ge2d_config->dst_para.x_rev ^= 1; |
| 381 | ge2d_config->dst_para.y_rev ^= 1; |
| 382 | } else if (dst_angle == 3) { |
| 383 | ge2d_config->dst_xy_swap = 1; |
| 384 | ge2d_config->dst_para.y_rev ^= 1; |
| 385 | } else { |
| 386 | ge2d_config->dst_xy_swap = 0; |
| 387 | } |
| 388 | } |
| 389 | |
| 390 | /* |
| 391 | * use ppmgr2 need to init struct ge2d_context_s, |
| 392 | * pixel_format, canvas_width, canvas_height, |
| 393 | * phy_addr, buffer_size, canvas_number. |
| 394 | */ |
| 395 | int ppmgr2_init(struct ppmgr2_device *ppd) |
| 396 | { |
| 397 | int i = 0; |
| 398 | /* switch_mod_gate_by_name("ge2d", 1); */ |
| 399 | ppd->context = create_ge2d_work_queue(); |
| 400 | if (!ppd->context) { |
| 401 | ppmgr2_printk(1, "create ge2d work queue error!\n"); |
| 402 | return -1; |
| 403 | } |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 404 | ppmgr2_printk(2, "%s!\n", __func__); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 405 | ppd->paint_mode = 0; |
| 406 | ppd->angle = 0; |
| 407 | ppd->mirror = 0; |
| 408 | ppd->ge2d_fmt = 0; |
| 409 | ppd->dst_width = 0; |
| 410 | ppd->dst_height = 0; |
| 411 | for (i = 0; i < IONVIDEO_POOL_SIZE; i++) { |
| 412 | ppd->phy_addr[i] = NULL; |
| 413 | ppd->canvas_id[i] = -1; |
| 414 | } |
| 415 | return 0; |
| 416 | } |
| 417 | |
| 418 | int ppmgr2_canvas_config(struct ppmgr2_device *ppd, int index) |
| 419 | { |
| 420 | int canvas_width; |
| 421 | int canvas_height; |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 422 | void *phy_addr; |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 423 | |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 424 | if (!ppd) { |
| 425 | ppmgr2_printk(1, "NULL physical address!\n"); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 426 | return -1; |
| 427 | } |
| 428 | |
| 429 | canvas_width = ppd->dst_buffer_width; |
| 430 | canvas_height = ppd->dst_buffer_height; |
| 431 | |
| 432 | if (index >= IONVIDEO_POOL_SIZE) { |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 433 | ppmgr2_printk(0, "canvas index too large! %d>=%d\n", index, |
| 434 | IONVIDEO_POOL_SIZE); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 435 | return -1; |
| 436 | } |
| 437 | |
| 438 | phy_addr = ppd->phy_addr[index]; |
| 439 | |
| 440 | if (IS_ERR_OR_NULL(phy_addr)) { |
| 441 | ppmgr2_printk(1, "NULL physical address!\n"); |
| 442 | return -1; |
| 443 | } |
| 444 | |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 445 | if (ppd->ge2d_fmt == GE2D_FORMAT_M24_NV21 || ppd->ge2d_fmt == |
| 446 | GE2D_FORMAT_M24_NV12) { |
| 447 | canvas_config(ionvideo_canvas_id[0], (ulong)phy_addr, |
| 448 | canvas_width, canvas_height, CANVAS_ADDR_NOWRAP, |
| 449 | CANVAS_BLKMODE_LINEAR); |
| 450 | canvas_config(ionvideo_canvas_id[1], |
| 451 | (ulong) |
| 452 | (phy_addr + (canvas_width * canvas_height)), |
| 453 | canvas_width, canvas_height >> 1, |
| 454 | CANVAS_ADDR_NOWRAP, |
| 455 | CANVAS_BLKMODE_LINEAR); |
| 456 | ppd->canvas_id[index] = ionvideo_canvas_id[0] | |
| 457 | (ionvideo_canvas_id[1] << 8); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 458 | } else if (ppd->ge2d_fmt == GE2D_FORMAT_S8_Y) { |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 459 | canvas_config(ionvideo_canvas_id[0], (ulong)phy_addr, |
| 460 | canvas_width, canvas_height, CANVAS_ADDR_NOWRAP, |
| 461 | CANVAS_BLKMODE_LINEAR); |
| 462 | canvas_config(ionvideo_canvas_id[1], |
| 463 | (ulong)(phy_addr + canvas_width * canvas_height), |
| 464 | canvas_width >> 1, canvas_height >> 1, |
| 465 | CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); |
| 466 | canvas_config(ionvideo_canvas_id[2], |
| 467 | (ulong) |
| 468 | (phy_addr + (canvas_width * canvas_height * 5 >> |
| 469 | 2)), |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 470 | canvas_width >> 1, canvas_height >> 1, |
| 471 | CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 472 | ppd->canvas_id[index] = ionvideo_canvas_id[0] |
| 473 | | (ionvideo_canvas_id[1] << 8) |
| 474 | | (ionvideo_canvas_id[2] << 16); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 475 | } else { |
| 476 | int bpp = 0; |
| 477 | |
| 478 | if (ppd->ge2d_fmt == GE2D_FORMAT_S32_ABGR) { |
| 479 | bpp = 4; |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 480 | } else if (ppd->ge2d_fmt == GE2D_FORMAT_S24_BGR || |
| 481 | ppd->ge2d_fmt == GE2D_FORMAT_S24_RGB) { |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 482 | bpp = 3; |
| 483 | } else if (ppd->ge2d_fmt == GE2D_FORMAT_S16_RGB_565) { |
| 484 | bpp = 2; |
| 485 | } else { |
| 486 | ppmgr2_printk(1, "Not support format!\n"); |
| 487 | return -1; |
| 488 | } |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 489 | canvas_config(ionvideo_canvas_id[0], (ulong)phy_addr, |
| 490 | canvas_width * bpp, canvas_height, |
| 491 | CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); |
| 492 | ppd->canvas_id[index] = ionvideo_canvas_id[0]; |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 493 | } |
| 494 | ppmgr2_printk(2, "canvas[%d] phy_addr:%p width:%d height:%d\n", index, |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 495 | phy_addr, canvas_width, canvas_height); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 496 | |
| 497 | return 0; |
| 498 | } |
| 499 | |
| 500 | void ppmgr2_set_angle(struct ppmgr2_device *ppd, int angle) |
| 501 | { |
| 502 | ppd->angle = angle; |
| 503 | } |
| 504 | |
| 505 | void ppmgr2_set_mirror(struct ppmgr2_device *ppd, int mirror) |
| 506 | { |
| 507 | ppd->mirror = mirror; |
| 508 | } |
| 509 | |
| 510 | void ppmgr2_set_paint_mode(struct ppmgr2_device *ppd, int paint_mode) |
| 511 | { |
| 512 | ppd->paint_mode = paint_mode; |
| 513 | } |
| 514 | |
| 515 | int ppmgr2_process(struct vframe_s *vf, struct ppmgr2_device *ppd, int index) |
| 516 | { |
| 517 | int ret = 0; |
| 518 | struct vframe_s *src_vf = vf; |
| 519 | int src_position[4] = {0}; |
| 520 | int dst_paint_position[4] = {0}, dst_plane_position[4] = {0}; |
| 521 | int dst_pixel_format = ppd->ge2d_fmt; |
| 522 | struct ge2d_context_s *context = ppd->context; |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 523 | struct config_para_ex_s *ge2d_config = &ppd->ge2d_config; |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 524 | int angle = (ppd->angle + src_vf->orientation) % 4; |
| 525 | int dst_canvas_id = 0; |
| 526 | |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 527 | if (!ppd->phy_addr[index]) { |
| 528 | pr_err("ionvideo:NULL physical address!\n"); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 529 | return -1; |
| 530 | } |
| 531 | |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 532 | if (src_vf->type & VIDTYPE_INTERLACE) { |
| 533 | if ((ppd->bottom_first && src_vf->type & 0x2) || |
| 534 | (ppd->bottom_first == 0 && |
| 535 | (src_vf->type & 0x2) == 0)) { |
| 536 | return -EAGAIN; |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 537 | } |
| 538 | } |
| 539 | |
| 540 | mutex_lock(ppd->ge2d_canvas_mutex); |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 541 | ionvideo_alloc_canvas(); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 542 | ppmgr2_canvas_config(ppd, index); |
| 543 | dst_canvas_id = ppd->canvas_id[index]; |
| 544 | src_position[0] = 0; |
| 545 | src_position[1] = 0; |
| 546 | src_position[2] = src_vf->width; |
| 547 | src_position[3] = src_vf->height; |
| 548 | if (src_position[2] == 0 || src_position[3] == 0) { |
| 549 | ppmgr2_printk(1, "Source frame error!\n"); |
| 550 | mutex_unlock(ppd->ge2d_canvas_mutex); |
| 551 | return -1; |
| 552 | } |
| 553 | dst_plane_position[0] = 0; |
| 554 | dst_plane_position[1] = 0; |
| 555 | dst_plane_position[2] = ppd->dst_width; |
| 556 | dst_plane_position[3] = ppd->dst_height; |
| 557 | |
| 558 | ge2d_src_config(src_vf, ge2d_config); |
| 559 | |
| 560 | ge2d_mirror_config(ppd->mirror, ge2d_config); |
| 561 | ge2d_angle_config(angle, ge2d_config); |
| 562 | paint_mode_convert(ppd->paint_mode, src_position, dst_paint_position, |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 563 | dst_plane_position); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 564 | |
| 565 | if (src_vf->type & VIDTYPE_INTERLACE) |
| 566 | src_position[3] = src_vf->height >> 1; |
| 567 | |
| 568 | ret = ge2d_paint_dst(context, ge2d_config, dst_canvas_id, |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 569 | dst_pixel_format, src_position, |
| 570 | dst_paint_position, dst_plane_position); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 571 | |
| 572 | mutex_unlock(ppd->ge2d_canvas_mutex); |
| 573 | |
| 574 | return ret; |
| 575 | } |
| 576 | |
| 577 | void ppmgr2_release(struct ppmgr2_device *ppd) |
| 578 | { |
| 579 | if (ppd->context) |
| 580 | destroy_ge2d_work_queue(ppd->context); |
| 581 | |
| 582 | /* switch_mod_gate_by_name("ge2d", 0); */ |
Googler | 9398cc3 | 2022-12-02 17:21:52 +0800 | [diff] [blame^] | 583 | ppmgr2_printk(2, "%s!\n", __func__); |
Googler | 9726be6 | 2022-12-14 05:53:31 +0000 | [diff] [blame] | 584 | } |
| 585 | |
| 586 | int v4l_to_ge2d_format(int v4l2_format) |
| 587 | { |
| 588 | int format = GE2D_FORMAT_M24_NV21; |
| 589 | |
| 590 | switch (v4l2_format) { |
| 591 | case V4L2_PIX_FMT_RGB32: |
| 592 | format = GE2D_FORMAT_S32_ABGR; |
| 593 | break; |
| 594 | case V4L2_PIX_FMT_RGB565: |
| 595 | format = GE2D_FORMAT_S16_RGB_565; |
| 596 | break; |
| 597 | case V4L2_PIX_FMT_BGR24: |
| 598 | format = GE2D_FORMAT_S24_RGB; |
| 599 | break; |
| 600 | case V4L2_PIX_FMT_RGB24: |
| 601 | format = GE2D_FORMAT_S24_BGR; |
| 602 | break; |
| 603 | case V4L2_PIX_FMT_NV12: |
| 604 | format = GE2D_FORMAT_M24_NV12; |
| 605 | break; |
| 606 | case V4L2_PIX_FMT_NV21: |
| 607 | format = GE2D_FORMAT_M24_NV21; |
| 608 | break; |
| 609 | case V4L2_PIX_FMT_YUV420: |
| 610 | case V4L2_PIX_FMT_YVU420: |
| 611 | format = GE2D_FORMAT_S8_Y; |
| 612 | break; |
| 613 | default: |
| 614 | break; |
| 615 | } |
| 616 | return format; |
| 617 | } |