hai.cao | 8c827c0 | 2023-02-28 11:12:05 +0800 | [diff] [blame] | 1 | // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| 2 | /* |
| 3 | * Copyright (c) 2019 Amlogic, Inc. All rights reserved. |
| 4 | */ |
| 5 | |
| 6 | #include <common.h> |
| 7 | #include <cpu_func.h> |
| 8 | #include <amlogic/lcd.h> |
| 9 | #include <command.h> |
| 10 | #include <asm/byteorder.h> |
| 11 | #include <malloc.h> |
| 12 | #include <splash.h> |
| 13 | #include <image.h> |
| 14 | #include <amlogic/video_fb.h> |
| 15 | #include <amlogic/video.h> |
| 16 | #include <amlogic/fb.h> |
| 17 | #ifdef CONFIG_AML_HDMITX |
yuhua.lin | 0dd0203 | 2024-11-21 16:59:59 +0800 | [diff] [blame] | 18 | #include <amlogic/media/vout/hdmitx21/hdmitx_ext.h> |
hai.cao | 8c827c0 | 2023-02-28 11:12:05 +0800 | [diff] [blame] | 19 | #endif |
| 20 | |
| 21 | int osd_enabled = 0; |
| 22 | /* Graphic Device */ |
| 23 | static GraphicDevice *gdev = NULL; |
| 24 | |
| 25 | static int do_osd_open(cmd_tbl_t *cmdtp, int flag, int argc, |
| 26 | char *const argv[]) |
| 27 | { |
| 28 | char *s; |
| 29 | uint fb_for_4k2k = 0; |
| 30 | |
| 31 | s = env_get("fb_for_4k2k"); |
| 32 | if (s) { |
| 33 | fb_for_4k2k = simple_strtoul(s, NULL, 10) ? 1 : 0; |
| 34 | printf("[OSD]using fb_for_4k2k %d\n", fb_for_4k2k); |
| 35 | } |
| 36 | osd_set_4k2k_fb_mode_hw(fb_for_4k2k); |
| 37 | |
| 38 | gdev = video_hw_init(RECT_MODE); |
| 39 | if (gdev == NULL) { |
| 40 | printf("Initialize video device failed!\n"); |
| 41 | return 1; |
| 42 | } |
| 43 | osd_enabled = 1; |
| 44 | return 0; |
| 45 | } |
| 46 | |
| 47 | static int do_osd_enable(cmd_tbl_t *cmdtp, int flag, int argc, |
| 48 | char *const argv[]) |
| 49 | { |
| 50 | int index = 0; |
| 51 | |
| 52 | index = get_osd_layer(); |
| 53 | if (index >= 0) |
| 54 | osd_enable_hw(index, 1); |
| 55 | |
| 56 | return 0; |
| 57 | } |
| 58 | |
| 59 | static int do_osd_close(cmd_tbl_t *cmdtp, int flag, int argc, |
| 60 | char *const argv[]) |
| 61 | { |
| 62 | |
| 63 | uint index = 0; |
| 64 | |
| 65 | index = get_osd_layer(); |
| 66 | |
| 67 | if (gdev == NULL) |
| 68 | return 1; |
| 69 | |
| 70 | gdev = NULL; |
yuhua.lin | 0dd0203 | 2024-11-21 16:59:59 +0800 | [diff] [blame] | 71 | if (is_vppx(index)) { |
hai.cao | 8c827c0 | 2023-02-28 11:12:05 +0800 | [diff] [blame] | 72 | osd_enable_hw(index, 0); |
| 73 | if (get_osd_viux_scale_cap()) |
| 74 | osd_set_free_scale_enable_hw(index, 0); |
| 75 | } else { |
| 76 | osd_enable_hw(OSD1, 0); |
| 77 | osd_enable_hw(OSD2, 0); |
| 78 | osd_set_free_scale_enable_hw(OSD1, 0); |
| 79 | osd_set_free_scale_enable_hw(OSD2, 0); |
| 80 | } |
| 81 | |
| 82 | osd_enabled = 0; |
| 83 | |
| 84 | return 0; |
| 85 | } |
| 86 | |
| 87 | static int do_osd_clear(cmd_tbl_t *cmdtp, int flag, int argc, |
| 88 | char *const argv[]) |
| 89 | { |
| 90 | #ifdef OSD_SCALE_ENABLE |
| 91 | uint index = 0; |
| 92 | ulong fb_addr; |
| 93 | ulong fb_len; |
| 94 | #endif |
| 95 | if (gdev == NULL) { |
| 96 | printf("Please enable osd device first!\n"); |
| 97 | return 1; |
| 98 | } |
| 99 | |
| 100 | #ifdef OSD_SCALE_ENABLE |
| 101 | index = get_osd_layer(); |
| 102 | |
| 103 | fb_addr = (ulong)gdev->frameAdrs + get_fb_offset(index); |
| 104 | fb_len = get_fb_len(index); |
| 105 | memset((void *)fb_addr, 0, fb_len); |
| 106 | flush_cache(fb_addr, fb_len); |
| 107 | #else |
| 108 | fb_len = CANVAS_ALIGNED(gdev->winSizeX * gdev->gdfBytesPP) * |
| 109 | gdev->winSizeY; |
| 110 | memset((void *)(long long)(gdev->frameAdrs), 0, fb_len); |
| 111 | |
| 112 | flush_cache(gdev->frameAdrs, fb_len); |
| 113 | #endif |
| 114 | return 0; |
| 115 | } |
| 116 | |
| 117 | static int do_osd_debug(cmd_tbl_t *cmdtp, int flag, int argc, |
| 118 | char *const argv[]) |
| 119 | { |
| 120 | int ret = 0; |
| 121 | int level = 0; |
| 122 | |
| 123 | switch (argc) { |
| 124 | case 1: |
| 125 | osd_debug(); |
| 126 | break; |
| 127 | case 2: |
| 128 | level = simple_strtoul(argv[1], NULL, 10); |
| 129 | osd_set_log_level(level); |
| 130 | break; |
| 131 | default: |
| 132 | return CMD_RET_USAGE; |
| 133 | } |
| 134 | |
| 135 | return ret; |
| 136 | } |
| 137 | |
| 138 | static int do_osd_test(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) |
| 139 | { |
| 140 | int ret = 0; |
| 141 | switch (argc) { |
| 142 | case 1: |
| 143 | osd_test(); |
| 144 | break; |
| 145 | case 2: |
| 146 | osd_rma_test(simple_strtoul(argv[1], NULL, 10)); |
| 147 | break; |
yuhua.lin | 0dd0203 | 2024-11-21 16:59:59 +0800 | [diff] [blame] | 148 | case 3: |
| 149 | osd_rma_test_with_addr(simple_strtoul(argv[1], NULL, 16), |
| 150 | simple_strtoul(argv[2], NULL, 16)); |
| 151 | break; |
hai.cao | 8c827c0 | 2023-02-28 11:12:05 +0800 | [diff] [blame] | 152 | default: |
| 153 | return CMD_RET_USAGE; |
| 154 | } |
| 155 | return ret; |
| 156 | } |
| 157 | |
| 158 | static int do_osd_display(cmd_tbl_t *cmdtp, int flag, int argc, |
| 159 | char *const argv[]) |
| 160 | { |
| 161 | int ret = 0; |
| 162 | int x = 0, y = 0; |
| 163 | ulong addr; |
| 164 | |
| 165 | if (gdev == NULL) { |
| 166 | printf("do_osd_display, enable osd device first!\n"); |
| 167 | return 1; |
| 168 | } |
| 169 | |
| 170 | splash_get_pos(&x, &y); |
| 171 | |
| 172 | switch (argc) { |
| 173 | case 1: /* use load_addr as default address */ |
| 174 | addr = image_load_addr; |
| 175 | break; |
| 176 | case 2: /* use argument */ |
| 177 | addr = simple_strtoul(argv[1], NULL, 16); |
| 178 | break; |
| 179 | case 4: |
| 180 | addr = simple_strtoul(argv[1], NULL, 16); |
| 181 | x = simple_strtoul(argv[2], NULL, 10); |
| 182 | y = simple_strtoul(argv[3], NULL, 10); |
| 183 | break; |
| 184 | default: |
| 185 | return CMD_RET_USAGE; |
| 186 | } |
| 187 | |
| 188 | ret = video_display_bitmap((unsigned long)addr, x, y); |
| 189 | |
| 190 | return ret; |
| 191 | } |
| 192 | |
| 193 | static int do_osd_set(cmd_tbl_t *cmdtp, int flag, int argc, |
| 194 | char *const argv[]) |
| 195 | { |
| 196 | int i; |
| 197 | ulong osdID; |
| 198 | char *str = NULL; |
| 199 | char *hist_env_key[12] = {"hist_max_min_osd0","hist_spl_val_osd0","hist_spl_pix_cnt_osd0","hist_cheoma_sum_osd0", |
| 200 | "hist_max_min_osd1","hist_spl_val_osd1","hist_spl_pix_cnt_osd1","hist_cheoma_sum_osd1", |
| 201 | "hist_max_min_osd2","hist_spl_val_osd2","hist_spl_pix_cnt_osd2","hist_cheoma_sum_osd2"}; |
| 202 | if (argc != 6) { |
| 203 | return CMD_RET_USAGE; |
| 204 | } |
| 205 | osdID = simple_strtoul(argv[1], NULL, 10); |
| 206 | |
| 207 | if (osdID > 2) { |
| 208 | printf("=== osdID is wrong. ===\n"); |
| 209 | return 1; |
| 210 | } |
| 211 | |
| 212 | for (i = osdID * 4; i < (osdID + 1) * 4; i++) { |
| 213 | str = env_get(hist_env_key[i]); |
| 214 | if (str) { |
| 215 | env_set(hist_env_key[i], argv[i%4+2]); |
| 216 | printf("set %s : %s\n", hist_env_key[i], env_get(hist_env_key[i])); |
| 217 | } |
| 218 | } |
| 219 | return 0; |
| 220 | } |
| 221 | |
| 222 | static int do_osd_get(cmd_tbl_t *cmdtp, int flag, int argc, |
| 223 | char *const argv[]) |
| 224 | { |
| 225 | int i; |
| 226 | char *str = NULL; |
| 227 | char *hist_env_key[12] = {"hist_max_min_osd0","hist_spl_val_osd0","hist_spl_pix_cnt_osd0","hist_cheoma_sum_osd0", |
| 228 | "hist_max_min_osd1","hist_spl_val_osd1","hist_spl_pix_cnt_osd1","hist_cheoma_sum_osd1", |
| 229 | "hist_max_min_osd2","hist_spl_val_osd2","hist_spl_pix_cnt_osd2","hist_cheoma_sum_osd2"}; |
| 230 | for (i = 0; i < 12; i++) { |
| 231 | str = env_get(hist_env_key[i]); |
| 232 | if (str) |
| 233 | printf("%s : %s\n", hist_env_key[i], str); |
| 234 | } |
| 235 | |
| 236 | return 0; |
| 237 | } |
| 238 | |
| 239 | static int do_osd_dual_logo(cmd_tbl_t *cmdtp, int flag, int argc, |
| 240 | char *const argv[]) |
| 241 | { |
| 242 | #ifdef CONFIG_AML_HDMITX |
| 243 | int st = 0; |
hai.cao | 8c827c0 | 2023-02-28 11:12:05 +0800 | [diff] [blame] | 244 | |
| 245 | /* detect hdmi plugin or not */ |
yuhua.lin | 0dd0203 | 2024-11-21 16:59:59 +0800 | [diff] [blame] | 246 | st = hdmitx_get_hpd_state_ext(); |
hai.cao | 8c827c0 | 2023-02-28 11:12:05 +0800 | [diff] [blame] | 247 | printf("osd: hpd_state=%c\n", st ? '1' : '0'); |
| 248 | |
yuhua.lin | 0dd0203 | 2024-11-21 16:59:59 +0800 | [diff] [blame] | 249 | if (env_get("set_logo_on") && strchr(env_get("set_logo_on"), '3')) |
| 250 | env_set("logo3_on", "on"); |
| 251 | else |
| 252 | env_set("logo3_on", "off"); |
| 253 | if (env_get("set_logo_on") && strchr(env_get("set_logo_on"), '2')) |
| 254 | env_set("logo2_on", "on"); |
| 255 | else |
| 256 | env_set("logo2_on", "off"); |
| 257 | if (env_get("set_logo_on") && strchr(env_get("set_logo_on"), '1')) |
| 258 | env_set("logo1_on", "on"); |
| 259 | else |
| 260 | env_set("logo1_on", "off"); |
| 261 | |
hai.cao | 8c827c0 | 2023-02-28 11:12:05 +0800 | [diff] [blame] | 262 | if (st) { |
| 263 | /* hdmi plugin, dual logo display |
| 264 | * CONFIG_RECOVERY_DUAL_LOGO is given priority in recovery |
| 265 | */ |
yuhua.lin | 0dd0203 | 2024-11-21 16:59:59 +0800 | [diff] [blame] | 266 | if (env_get("reboot_mode") && !strncmp(env_get("reboot_mode"), |
| 267 | "factory_reset", 13)) { |
hai.cao | 8c827c0 | 2023-02-28 11:12:05 +0800 | [diff] [blame] | 268 | #if defined(CONFIG_RECOVERY_DUAL_LOGO) |
| 269 | run_command(CONFIG_RECOVERY_DUAL_LOGO, 0); |
| 270 | #else |
| 271 | #if defined(CONFIG_DUAL_LOGO) |
| 272 | printf("osd: use dual logo cmd macro in recovery mode\n"); |
| 273 | run_command(CONFIG_DUAL_LOGO, 0); |
| 274 | #else |
| 275 | printf("osd: dual logo cmd macro is not defined in recovery mode\n"); |
| 276 | #endif |
| 277 | #endif |
| 278 | } else { |
| 279 | #if defined(CONFIG_DUAL_LOGO) |
| 280 | run_command(CONFIG_DUAL_LOGO, 0); |
| 281 | #else |
| 282 | printf("osd: dual logo cmd macro is not defined\n"); |
| 283 | #endif |
| 284 | } |
| 285 | } else { |
| 286 | /* hdmi plugout, single logo display */ |
| 287 | #if defined(CONFIG_SINGLE_LOGO) |
| 288 | run_command(CONFIG_SINGLE_LOGO, 0); |
| 289 | #else |
| 290 | printf("osd: single logo cmd macro is not defined\n"); |
| 291 | #endif |
| 292 | } |
| 293 | #else |
| 294 | printf("osd: no hdmitx_device defined\n"); |
| 295 | #if defined(CONFIG_SINGLE_LOGO) |
| 296 | run_command(CONFIG_SINGLE_LOGO, 0); |
| 297 | #else |
| 298 | printf("osd: single logo cmd macro is not defined\n"); |
| 299 | #endif |
| 300 | #endif |
| 301 | |
| 302 | return 0; |
| 303 | } |
| 304 | |
| 305 | static cmd_tbl_t cmd_osd_sub[] = { |
| 306 | U_BOOT_CMD_MKENT(open, 2, 0, do_osd_open, "", ""), |
| 307 | U_BOOT_CMD_MKENT(enable, 2, 0, do_osd_enable, "", ""), |
| 308 | U_BOOT_CMD_MKENT(close, 2, 0, do_osd_close, "", ""), |
| 309 | U_BOOT_CMD_MKENT(clear, 2, 0, do_osd_clear, "", ""), |
| 310 | U_BOOT_CMD_MKENT(debug, 2, 0, do_osd_debug, "", ""), |
| 311 | U_BOOT_CMD_MKENT(test, 2, 0, do_osd_test, "", ""), |
| 312 | U_BOOT_CMD_MKENT(display, 5, 0, do_osd_display, "", ""), |
| 313 | U_BOOT_CMD_MKENT(set, 7, 0, do_osd_set, "", ""), |
| 314 | U_BOOT_CMD_MKENT(get, 2, 0, do_osd_get, "", ""), |
| 315 | U_BOOT_CMD_MKENT(dual_logo, 2, 0, do_osd_dual_logo, "", ""), |
| 316 | }; |
| 317 | |
| 318 | static int do_osd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) |
| 319 | { |
| 320 | cmd_tbl_t *c; |
| 321 | |
| 322 | /* Strip off leading 'osd' command argument */ |
| 323 | argc--; |
| 324 | argv++; |
| 325 | |
| 326 | c = find_cmd_tbl(argv[0], &cmd_osd_sub[0], ARRAY_SIZE(cmd_osd_sub)); |
| 327 | |
| 328 | if (c) |
| 329 | return c->cmd(cmdtp, flag, argc, argv); |
| 330 | else |
| 331 | return CMD_RET_USAGE; |
| 332 | } |
| 333 | |
| 334 | U_BOOT_CMD( |
| 335 | osd, 7, 1, do_osd, |
| 336 | "osd sub-system", |
| 337 | "open - open osd device\n" |
| 338 | "osd enable - enable osd device\n" |
| 339 | "osd close - close osd device\n" |
| 340 | "osd clear - clear osd framebuffer\n" |
| 341 | "osd debug - debug osd device\n" |
| 342 | "osd test [osdID] - test osd device\n" |
| 343 | "osd display <imageAddr> [x y] - display image\n" |
| 344 | "osd set <osdID> <a> <b> <c> <d> - set Hist GoldenData in env\n" |
| 345 | " a for hist_max_min\n" |
| 346 | " b for hist_spl_val\n" |
| 347 | " c for hist_spl_pix_cnt\n" |
| 348 | " d for hist_cheoma_sum\n" |
| 349 | "osd get - get Hist GoldenData from env\n" |
| 350 | "osd dual_logo - detect hdmi hpd, then display logo" |
| 351 | ); |
| 352 | |