Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: iris: Add support for SM8750 (VPU v3.5)

Add support for SM8750 Iris codec with major differences against
previous generation SM8650:

1. New clocks and new resets, thus new power up and power down
sequences,

2. New WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0 register programmed
during boot-up

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Bryan O'Donoghue <bod@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>

authored by

Krzysztof Kozlowski and committed by
Mauro Carvalho Chehab
dbd57932 1f01a498

+271 -1
+5 -1
drivers/media/platform/qcom/iris/iris_platform_common.h
··· 38 38 extern struct iris_platform_data sm8250_data; 39 39 extern struct iris_platform_data sm8550_data; 40 40 extern struct iris_platform_data sm8650_data; 41 + extern struct iris_platform_data sm8750_data; 41 42 42 43 enum platform_clk_type { 43 - IRIS_AXI_CLK, 44 + IRIS_AXI_CLK, /* AXI0 in case of platforms with multiple AXI clocks */ 44 45 IRIS_CTRL_CLK, 45 46 IRIS_HW_CLK, 47 + IRIS_AXI1_CLK, 48 + IRIS_CTRL_FREERUN_CLK, 49 + IRIS_HW_FREERUN_CLK, 46 50 }; 47 51 48 52 struct platform_clk_data {
+68
drivers/media/platform/qcom/iris/iris_platform_gen2.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 + * Copyright (c) 2025 Linaro Ltd 4 5 */ 5 6 6 7 #include "iris_core.h" ··· 13 12 14 13 #include "iris_platform_qcs8300.h" 15 14 #include "iris_platform_sm8650.h" 15 + #include "iris_platform_sm8750.h" 16 16 17 17 #define VIDEO_ARCH_LX 1 18 18 ··· 420 418 /* Upper bound of DMA address range */ 421 419 .dma_mask = 0xe0000000 - 1, 422 420 .fwname = "qcom/vpu/vpu33_p4.mbn", 421 + .pas_id = IRIS_PAS_ID, 422 + .inst_caps = &platform_inst_cap_sm8550, 423 + .inst_fw_caps = inst_fw_cap_sm8550, 424 + .inst_fw_caps_size = ARRAY_SIZE(inst_fw_cap_sm8550), 425 + .tz_cp_config_data = &tz_cp_config_sm8550, 426 + .core_arch = VIDEO_ARCH_LX, 427 + .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE, 428 + .ubwc_config = &ubwc_config_sm8550, 429 + .num_vpp_pipe = 4, 430 + .max_session_count = 16, 431 + .max_core_mbpf = NUM_MBS_8K * 2, 432 + .input_config_params_default = 433 + sm8550_vdec_input_config_params_default, 434 + .input_config_params_default_size = 435 + ARRAY_SIZE(sm8550_vdec_input_config_params_default), 436 + .input_config_params_hevc = 437 + sm8550_vdec_input_config_param_hevc, 438 + .input_config_params_hevc_size = 439 + ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), 440 + .input_config_params_vp9 = 441 + sm8550_vdec_input_config_param_vp9, 442 + .input_config_params_vp9_size = 443 + ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), 444 + .output_config_params = 445 + sm8550_vdec_output_config_params, 446 + .output_config_params_size = 447 + ARRAY_SIZE(sm8550_vdec_output_config_params), 448 + .dec_input_prop = sm8550_vdec_subscribe_input_properties, 449 + .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), 450 + .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, 451 + .dec_output_prop_avc_size = 452 + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_avc), 453 + .dec_output_prop_hevc = sm8550_vdec_subscribe_output_properties_hevc, 454 + .dec_output_prop_hevc_size = 455 + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_hevc), 456 + .dec_output_prop_vp9 = sm8550_vdec_subscribe_output_properties_vp9, 457 + .dec_output_prop_vp9_size = 458 + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_vp9), 459 + 460 + .dec_ip_int_buf_tbl = sm8550_dec_ip_int_buf_tbl, 461 + .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl), 462 + .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, 463 + .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), 464 + }; 465 + 466 + struct iris_platform_data sm8750_data = { 467 + .get_instance = iris_hfi_gen2_get_instance, 468 + .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, 469 + .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, 470 + .vpu_ops = &iris_vpu35_ops, 471 + .set_preset_registers = iris_set_sm8550_preset_registers, 472 + .icc_tbl = sm8550_icc_table, 473 + .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), 474 + .clk_rst_tbl = sm8750_clk_reset_table, 475 + .clk_rst_tbl_size = ARRAY_SIZE(sm8750_clk_reset_table), 476 + .bw_tbl_dec = sm8550_bw_table_dec, 477 + .bw_tbl_dec_size = ARRAY_SIZE(sm8550_bw_table_dec), 478 + .pmdomain_tbl = sm8550_pmdomain_table, 479 + .pmdomain_tbl_size = ARRAY_SIZE(sm8550_pmdomain_table), 480 + .opp_pd_tbl = sm8550_opp_pd_table, 481 + .opp_pd_tbl_size = ARRAY_SIZE(sm8550_opp_pd_table), 482 + .clk_tbl = sm8750_clk_table, 483 + .clk_tbl_size = ARRAY_SIZE(sm8750_clk_table), 484 + /* Upper bound of DMA address range */ 485 + .dma_mask = 0xe0000000 - 1, 486 + .fwname = "qcom/vpu/vpu35_p4.mbn", 423 487 .pas_id = IRIS_PAS_ID, 424 488 .inst_caps = &platform_inst_cap_sm8550, 425 489 .inst_fw_caps = inst_fw_cap_sm8550,
+22
drivers/media/platform/qcom/iris/iris_platform_sm8750.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2025 Linaro Ltd 4 + */ 5 + 6 + #ifndef __MEDIA_IRIS_PLATFORM_SM8750_H__ 7 + #define __MEDIA_IRIS_PLATFORM_SM8750_H__ 8 + 9 + static const char * const sm8750_clk_reset_table[] = { 10 + "bus0", "bus1", "core", "vcodec0_core" 11 + }; 12 + 13 + static const struct platform_clk_data sm8750_clk_table[] = { 14 + {IRIS_AXI_CLK, "iface" }, 15 + {IRIS_CTRL_CLK, "core" }, 16 + {IRIS_HW_CLK, "vcodec0_core" }, 17 + {IRIS_AXI1_CLK, "iface1" }, 18 + {IRIS_CTRL_FREERUN_CLK, "core_freerun" }, 19 + {IRIS_HW_FREERUN_CLK, "vcodec0_core_freerun" }, 20 + }; 21 + 22 + #endif
+4
drivers/media/platform/qcom/iris/iris_probe.c
··· 353 353 .compatible = "qcom,sm8650-iris", 354 354 .data = &sm8650_data, 355 355 }, 356 + { 357 + .compatible = "qcom,sm8750-iris", 358 + .data = &sm8750_data, 359 + }, 356 360 { }, 357 361 }; 358 362 MODULE_DEVICE_TABLE(of, iris_dt_match);
+166
drivers/media/platform/qcom/iris/iris_vpu3x.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 + * Copyright (c) 2025 Linaro Ltd 4 5 */ 5 6 6 7 #include <linux/iopoll.h> ··· 25 24 #define NOC_LPI_STATUS_ACTIVE BIT(2) /* Indicates the NOC is active */ 26 25 #define WRAPPER_CORE_CLOCK_CONFIG (WRAPPER_BASE_OFFS + 0x88) 27 26 #define CORE_CLK_RUN 0x0 27 + /* VPU v3.5 */ 28 + #define WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0 (WRAPPER_BASE_OFFS + 0x78) 28 29 29 30 #define WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG (WRAPPER_TZ_BASE_OFFS + 0x14) 30 31 #define CTL_AXI_CLK_HALT BIT(0) ··· 58 55 #define AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL (AON_BASE_OFFS + 0x20) 59 56 #define NOC_HALT BIT(0) 60 57 #define AON_WRAPPER_SPARE (AON_BASE_OFFS + 0x28) 58 + #define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL (AON_BASE_OFFS + 0x2C) 59 + #define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS (AON_BASE_OFFS + 0x30) 61 60 62 61 static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core) 63 62 { ··· 258 253 return 0; 259 254 } 260 255 256 + static int iris_vpu35_power_on_hw(struct iris_core *core) 257 + { 258 + int ret; 259 + 260 + ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); 261 + if (ret) 262 + return ret; 263 + 264 + ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); 265 + if (ret) 266 + goto err_disable_power; 267 + 268 + ret = iris_prepare_enable_clock(core, IRIS_HW_FREERUN_CLK); 269 + if (ret) 270 + goto err_disable_axi_clk; 271 + 272 + ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); 273 + if (ret) 274 + goto err_disable_hw_free_clk; 275 + 276 + ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], true); 277 + if (ret) 278 + goto err_disable_hw_clk; 279 + 280 + return 0; 281 + 282 + err_disable_hw_clk: 283 + iris_disable_unprepare_clock(core, IRIS_HW_CLK); 284 + err_disable_hw_free_clk: 285 + iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); 286 + err_disable_axi_clk: 287 + iris_disable_unprepare_clock(core, IRIS_AXI_CLK); 288 + err_disable_power: 289 + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); 290 + 291 + return ret; 292 + } 293 + 294 + static void iris_vpu35_power_off_hw(struct iris_core *core) 295 + { 296 + iris_vpu33_power_off_hardware(core); 297 + 298 + iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); 299 + iris_disable_unprepare_clock(core, IRIS_AXI_CLK); 300 + } 301 + 302 + static int iris_vpu35_power_off_controller(struct iris_core *core) 303 + { 304 + u32 clk_rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; 305 + unsigned int count = 0; 306 + u32 val = 0; 307 + bool handshake_done, handshake_busy; 308 + int ret; 309 + 310 + writel(MSK_SIGNAL_FROM_TENSILICA | MSK_CORE_POWER_ON, core->reg_base + CPU_CS_X2RPMH); 311 + 312 + writel(REQ_POWER_DOWN_PREP, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL); 313 + 314 + ret = readl_poll_timeout(core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_STATUS, 315 + val, val & BIT(0), 200, 2000); 316 + if (ret) 317 + goto disable_power; 318 + 319 + writel(0, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL); 320 + 321 + /* Retry up to 1000 times as recommended by hardware documentation */ 322 + do { 323 + /* set MNoC to low power */ 324 + writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); 325 + 326 + udelay(15); 327 + 328 + val = readl(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS); 329 + 330 + handshake_done = val & NOC_LPI_STATUS_DONE; 331 + handshake_busy = val & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE); 332 + 333 + if (handshake_done || !handshake_busy) 334 + break; 335 + 336 + writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); 337 + 338 + udelay(15); 339 + 340 + } while (++count < 1000); 341 + 342 + if (!handshake_done && handshake_busy) 343 + dev_err(core->dev, "LPI handshake timeout\n"); 344 + 345 + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS, 346 + val, val & BIT(0), 200, 2000); 347 + if (ret) 348 + goto disable_power; 349 + 350 + writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL); 351 + 352 + writel(0, core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL); 353 + 354 + ret = readl_poll_timeout(core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_STATUS, 355 + val, val == 0, 200, 2000); 356 + if (ret) 357 + goto disable_power; 358 + 359 + disable_power: 360 + iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); 361 + iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); 362 + iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); 363 + 364 + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); 365 + 366 + reset_control_bulk_reset(clk_rst_tbl_size, core->resets); 367 + 368 + return 0; 369 + } 370 + 371 + static int iris_vpu35_power_on_controller(struct iris_core *core) 372 + { 373 + int ret; 374 + 375 + ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); 376 + if (ret) 377 + return ret; 378 + 379 + ret = iris_prepare_enable_clock(core, IRIS_AXI1_CLK); 380 + if (ret) 381 + goto err_disable_power; 382 + 383 + ret = iris_prepare_enable_clock(core, IRIS_CTRL_FREERUN_CLK); 384 + if (ret) 385 + goto err_disable_axi1_clk; 386 + 387 + ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK); 388 + if (ret) 389 + goto err_disable_ctrl_free_clk; 390 + 391 + return 0; 392 + 393 + err_disable_ctrl_free_clk: 394 + iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); 395 + err_disable_axi1_clk: 396 + iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); 397 + err_disable_power: 398 + iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); 399 + 400 + return ret; 401 + } 402 + 403 + static void iris_vpu35_program_bootup_registers(struct iris_core *core) 404 + { 405 + writel(0x1, core->reg_base + WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0); 406 + } 407 + 261 408 static u64 iris_vpu3x_calculate_frequency(struct iris_inst *inst, size_t data_size) 262 409 { 263 410 struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; ··· 460 303 .power_on_hw = iris_vpu_power_on_hw, 461 304 .power_off_controller = iris_vpu33_power_off_controller, 462 305 .power_on_controller = iris_vpu_power_on_controller, 306 + .calc_freq = iris_vpu3x_calculate_frequency, 307 + }; 308 + 309 + const struct vpu_ops iris_vpu35_ops = { 310 + .power_off_hw = iris_vpu35_power_off_hw, 311 + .power_on_hw = iris_vpu35_power_on_hw, 312 + .power_off_controller = iris_vpu35_power_off_controller, 313 + .power_on_controller = iris_vpu35_power_on_controller, 314 + .program_bootup_registers = iris_vpu35_program_bootup_registers, 463 315 .calc_freq = iris_vpu3x_calculate_frequency, 464 316 };
+4
drivers/media/platform/qcom/iris/iris_vpu_common.c
··· 84 84 static void iris_vpu_setup_ucregion_memory_map(struct iris_core *core) 85 85 { 86 86 u32 queue_size, value; 87 + const struct vpu_ops *vpu_ops = core->iris_platform_data->vpu_ops; 87 88 88 89 /* Iris hardware requires 4K queue alignment */ 89 90 queue_size = ALIGN(sizeof(struct iris_hfi_queue_table_header) + ··· 106 105 value = (u32)core->sfr_daddr + core->iris_platform_data->core_arch; 107 106 writel(value, core->reg_base + SFR_ADDR); 108 107 } 108 + 109 + if (vpu_ops->program_bootup_registers) 110 + vpu_ops->program_bootup_registers(core); 109 111 } 110 112 111 113 int iris_vpu_boot_firmware(struct iris_core *core)
+2
drivers/media/platform/qcom/iris/iris_vpu_common.h
··· 11 11 extern const struct vpu_ops iris_vpu2_ops; 12 12 extern const struct vpu_ops iris_vpu3_ops; 13 13 extern const struct vpu_ops iris_vpu33_ops; 14 + extern const struct vpu_ops iris_vpu35_ops; 14 15 15 16 struct vpu_ops { 16 17 void (*power_off_hw)(struct iris_core *core); 17 18 int (*power_on_hw)(struct iris_core *core); 18 19 int (*power_off_controller)(struct iris_core *core); 19 20 int (*power_on_controller)(struct iris_core *core); 21 + void (*program_bootup_registers)(struct iris_core *core); 20 22 u64 (*calc_freq)(struct iris_inst *inst, size_t data_size); 21 23 }; 22 24