staticvoid malidp_write_gamma_table(struct malidp_hw_device *hwdev,
u32 data[MALIDP_COEFFTAB_NUM_COEFFS])
{ int i; /* Update all channels with a single gamma curve. */ const u32 gamma_write_mask = GENMASK(18, 16); /* * Always write an entire table, so the address field in * DE_COEFFTAB_ADDR is 0 and we can use the gamma_write_mask bitmask * directly.
*/
malidp_hw_write(hwdev, gamma_write_mask,
hwdev->hw->map.coeffs_base + MALIDP_COEF_TABLE_ADDR); for (i = 0; i < MALIDP_COEFFTAB_NUM_COEFFS; ++i)
malidp_hw_write(hwdev, data[i],
hwdev->hw->map.coeffs_base +
MALIDP_COEF_TABLE_DATA);
}
/* Set SE_CONTROL */ if (!s->scale_enable) {
val = malidp_hw_read(hwdev, se_control);
val &= ~MALIDP_SE_SCALING_EN;
malidp_hw_write(hwdev, val, se_control); return;
}
hwdev->hw->se_set_scaling_coeffs(hwdev, s, old_s);
val = malidp_hw_read(hwdev, se_control);
val |= MALIDP_SE_SCALING_EN | MALIDP_SE_ALPHA_EN;
val &= ~MALIDP_SE_ENH(MALIDP_SE_ENH_MASK);
val |= s->enhancer_enable ? MALIDP_SE_ENH(3) : 0;
val |= MALIDP_SE_RGBO_IF_EN;
malidp_hw_write(hwdev, val, se_control);
/* Set IN_SIZE & OUT_SIZE. */
val = MALIDP_SE_SET_V_SIZE(s->input_h) |
MALIDP_SE_SET_H_SIZE(s->input_w);
malidp_hw_write(hwdev, val, layer_control + MALIDP_SE_L0_IN_SIZE);
val = MALIDP_SE_SET_V_SIZE(s->output_h) |
MALIDP_SE_SET_H_SIZE(s->output_w);
malidp_hw_write(hwdev, val, layer_control + MALIDP_SE_L0_OUT_SIZE);
/* * set the "config valid" bit and wait until the hardware acts on it
*/ staticint malidp_set_and_wait_config_valid(struct drm_device *drm)
{ struct malidp_drm *malidp = drm_to_malidp(drm); struct malidp_hw_device *hwdev = malidp->dev; int ret;
hwdev->hw->set_config_valid(hwdev, 1); /* don't wait for config_valid flag if we are in config mode */ if (hwdev->hw->in_config_mode(hwdev)) {
atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE); return 0;
}
ret = wait_event_interruptible_timeout(malidp->wq,
atomic_read(&malidp->config_valid) == MALIDP_CONFIG_VALID_DONE,
msecs_to_jiffies(MALIDP_CONF_VALID_TIMEOUT));
if (malidp->crtc.state->active) { /* * if we have an event to deliver to userspace, make sure * the vblank is enabled as we are sending it from the IRQ * handler.
*/ if (malidp->event)
drm_crtc_vblank_get(&malidp->crtc);
/* only set config_valid if the CRTC is enabled */ if (malidp_set_and_wait_config_valid(drm) < 0) { /* * make a loop around the second CVAL setting and * try 5 times before giving up.
*/ while (loop--) { if (!malidp_set_and_wait_config_valid(drm)) break;
}
DRM_DEBUG_DRIVER("timed out waiting for updated configuration\n");
}
/* * set config_valid to a special value to let IRQ handlers * know that we are updating registers
*/
atomic_set(&malidp->config_valid, MALIDP_CONFIG_START);
malidp->dev->hw->set_config_valid(malidp->dev, 0);
/* * The DP500 CORE_ID register is in a different location, so check it * first. If the product id field matches, then this is DP500, otherwise * check the DP550/650 CORE_ID register.
*/
core_id = malidp_hw_read(hwdev, MALIDP500_DC_BASE + MALIDP_DE_CORE_ID); /* Offset 0x18 will never read 0x500 on products other than DP500. */
is_dp500 = (MALIDP_PRODUCT_ID(core_id) == 0x500);
dt_is_dp500 = strnstr(dev_id->compatible, compatstr_dp500, sizeof(dev_id->compatible)) != NULL; if (is_dp500 != dt_is_dp500) {
DRM_ERROR("Device-tree expects %s, but hardware %s DP500.\n",
dev_id->compatible, is_dp500 ? "is" : "is not"); returnfalse;
} elseif (!dt_is_dp500) {
u16 product_id; char buf[32];
hwdev->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(hwdev->regs)) return PTR_ERR(hwdev->regs);
hwdev->pclk = devm_clk_get(dev, "pclk"); if (IS_ERR(hwdev->pclk)) return PTR_ERR(hwdev->pclk);
hwdev->aclk = devm_clk_get(dev, "aclk"); if (IS_ERR(hwdev->aclk)) return PTR_ERR(hwdev->aclk);
hwdev->mclk = devm_clk_get(dev, "mclk"); if (IS_ERR(hwdev->mclk)) return PTR_ERR(hwdev->mclk);
hwdev->pxlclk = devm_clk_get(dev, "pxlclk"); if (IS_ERR(hwdev->pxlclk)) return PTR_ERR(hwdev->pxlclk);
/* Get the optional framebuffer memory resource */
ret = of_reserved_mem_device_init(dev); if (ret && ret != -ENODEV) return ret;
dev_set_drvdata(dev, drm);
/* Enable power management */
pm_runtime_enable(dev);
/* Resume device to enable the clocks */ if (pm_runtime_enabled(dev))
pm_runtime_get_sync(dev); else
malidp_runtime_pm_resume(dev);
dev_id = of_match_device(malidp_drm_of_match, dev); if (!dev_id) {
ret = -EINVAL; goto query_hw_fail;
}
if (!malidp_has_sufficient_address_space(res, dev_id)) {
DRM_ERROR("Insufficient address space in device-tree.\n");
ret = -EINVAL; goto query_hw_fail;
}
if (!malidp_is_compatible_hw_id(hwdev, dev_id)) {
ret = -EINVAL; goto query_hw_fail;
}
ret = hwdev->hw->query_hw(hwdev); if (ret) {
DRM_ERROR("Invalid HW configuration\n"); goto query_hw_fail;
}
version = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_DE_CORE_ID);
DRM_INFO("found ARM Mali-DP%3x version r%dp%d\n", version >> 16,
(version >> 12) & 0xf, (version >> 8) & 0xf);
malidp->core_id = version;
ret = of_property_read_u32(dev->of_node, "arm,malidp-arqos-value",
&hwdev->arqos_value); if (ret)
hwdev->arqos_value = 0x0;
/* set the number of lines used for output of RGB data */
ret = of_property_read_u8_array(dev->of_node, "arm,malidp-output-port-lines",
output_width, MAX_OUTPUT_CHANNELS); if (ret) goto query_hw_fail;
for (i = 0; i < MAX_OUTPUT_CHANNELS; i++)
out_depth = (out_depth << 8) | (output_width[i] & 0xf);
malidp_hw_write(hwdev, out_depth, hwdev->hw->map.out_depth_base);
hwdev->output_color_depth = out_depth;
ret = malidp_init(drm); if (ret < 0) goto query_hw_fail;
/* Set the CRTC's port so that the encoder component can find it */
malidp->crtc.port = of_graph_get_port_by_id(dev->of_node, 0);
ret = component_bind_all(dev, drm); if (ret) {
DRM_ERROR("Failed to bind all components\n"); goto bind_fail;
}
/* We expect to have a maximum of two encoders one for the actual * display and a virtual one for the writeback connector
*/
WARN_ON(drm->mode_config.num_encoder > 2);
list_for_each_entry(encoder, &drm->mode_config.encoder_list, head) {
encoder->possible_clones =
(1 << drm->mode_config.num_encoder) - 1;
}
ret = malidp_irq_init(pdev); if (ret < 0) goto irq_init_fail;
ret = drm_vblank_init(drm, drm->mode_config.num_crtc); if (ret < 0) {
DRM_ERROR("failed to initialise vblank\n"); goto vblank_fail;
}
pm_runtime_put(dev);
drm_mode_config_reset(drm);
drm_kms_helper_poll_init(drm);
ret = drm_dev_register(drm, 0); if (ret) goto register_fail;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.