staticenum port intel_dsi_seq_port_to_port(struct intel_dsi *intel_dsi,
u8 seq_port)
{ /* * If single link DSI is being used on any port, the VBT sequence block * send packet apparently always has 0 for the port. Just use the port * we have configured, and ignore the sequence block port.
*/ if (hweight8(intel_dsi->ports) == 1) return ffs(intel_dsi->ports) - 1;
if (seq_port) { if (intel_dsi->ports & BIT(PORT_B)) return PORT_B; if (intel_dsi->ports & BIT(PORT_C)) return PORT_C;
}
port = intel_dsi_seq_port_to_port(intel_dsi, seq_port);
if (drm_WARN_ON(display->drm, !intel_dsi->dsi_hosts[port])) goto out;
dsi_device = intel_dsi->dsi_hosts[port]->device; if (!dsi_device) {
drm_dbg_kms(display->drm, "no dsi device for port %c\n",
port_name(port)); goto out;
}
switch (type) { case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
mipi_dsi_generic_write(dsi_device, NULL, 0); break; case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
mipi_dsi_generic_write(dsi_device, data, 1); break; case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
mipi_dsi_generic_write(dsi_device, data, 2); break; case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM: case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM: case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
drm_dbg_kms(display->drm, "Generic Read not yet implemented or used\n"); break; case MIPI_DSI_GENERIC_LONG_WRITE:
mipi_dsi_generic_write(dsi_device, data, len); break; case MIPI_DSI_DCS_SHORT_WRITE:
mipi_dsi_dcs_write_buffer(dsi_device, data, 1); break; case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
mipi_dsi_dcs_write_buffer(dsi_device, data, 2); break; case MIPI_DSI_DCS_READ:
drm_dbg_kms(display->drm, "DCS Read not yet implemented or used\n"); break; case MIPI_DSI_DCS_LONG_WRITE:
mipi_dsi_dcs_write_buffer(dsi_device, data, len); break;
}
if (DISPLAY_VER(display) < 11)
vlv_dsi_wait_for_fifo_empty(intel_dsi, port);
staticvoid icl_native_gpio_set_value(struct intel_display *display, int gpio, bool value)
{ int index;
if (drm_WARN_ON(display->drm, DISPLAY_VER(display) == 11 && gpio >= MIPI_RESET_2)) return;
switch (gpio) { case MIPI_RESET_1: case MIPI_RESET_2:
index = gpio == MIPI_RESET_1 ? HPD_PORT_A : HPD_PORT_B;
/* * Disable HPD to set the pin to output, and set output * value. The HPD pin should not be enabled for DSI anyway, * assuming the board design and VBT are sane, and the pin isn't * used by a non-DSI encoder. * * The locking protects against concurrent SHOTPLUG_CTL_DDI * modifications in irq setup and handling.
*/
spin_lock_irq(&display->irq.lock);
intel_de_rmw(display, SHOTPLUG_CTL_DDI,
SHOTPLUG_CTL_DDI_HPD_ENABLE(index) |
SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index),
value ? SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index) : 0);
spin_unlock_irq(&display->irq.lock); break; case MIPI_AVDD_EN_1: case MIPI_AVDD_EN_2:
index = gpio == MIPI_AVDD_EN_1 ? 0 : 1;
intel_de_rmw(display, PP_CONTROL(display, index), PANEL_POWER_ON,
value ? PANEL_POWER_ON : 0); break; case MIPI_BKLT_EN_1: case MIPI_BKLT_EN_2:
index = gpio == MIPI_BKLT_EN_1 ? 0 : 1;
intel_de_rmw(display, PP_CONTROL(display, index), EDP_BLC_ENABLE,
value ? EDP_BLC_ENABLE : 0); break; case MIPI_AVEE_EN_1: case MIPI_AVEE_EN_2:
index = gpio == MIPI_AVEE_EN_1 ? 1 : 2;
intel_de_rmw(display, GPIO(display, index),
GPIO_CLOCK_VAL_OUT,
GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_DIR_OUT |
GPIO_CLOCK_VAL_MASK | (value ? GPIO_CLOCK_VAL_OUT : 0)); break; case MIPI_VIO_EN_1: case MIPI_VIO_EN_2:
index = gpio == MIPI_VIO_EN_1 ? 1 : 2;
drm_dbg_kms(display->drm, "GPIO index %u, number %u, source %u, native %s, set to %s\n",
gpio_index, gpio_number, gpio_source, str_yes_no(native), str_on_off(value));
ret = i2c_transfer(adapter, &msg, 1); if (ret < 0)
drm_err(display->drm, "Failed to xfer payload of size (%u) to reg (%u)\n",
payload_size, reg_offset);
/* byte 0 aka PMIC Flag is reserved */
i2c_address = get_unaligned_le16(data + 1);
reg_address = get_unaligned_le32(data + 3);
value = get_unaligned_le32(data + 7);
mask = get_unaligned_le32(data + 11);
ret = intel_soc_pmic_exec_mipi_pmic_seq_element(i2c_address,
reg_address,
value, mask); if (ret)
drm_err(display->drm, "%s failed, error: %d\n", __func__, ret); #else
drm_err(display->drm, "Your hardware requires CONFIG_PMIC_OPREGION and it is not set\n"); #endif
/* * MIPI Sequence from VBT #53 parsing logic * We have already separated each sequence during bios parsing * Following is generic execution function for any sequence
*/
/* Starting point, adjusted depending on dual link and burst mode */
intel_dsi->pclk = mode->clock;
/* In dual link mode each port needs half of pixel clock */ if (intel_dsi->dual_link) {
intel_dsi->pclk /= 2;
/* we can enable pixel_overlap if needed by panel. In this * case we need to increase the pixelclock for extra pixels
*/ if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
intel_dsi->pclk += DIV_ROUND_UP(mode->vtotal * intel_dsi->pixel_overlap * 60, 1000);
}
}
/* Burst Mode Ratio * Target ddr frequency from VBT / non burst ddr freq * multiply by 100 to preserve remainder
*/ if (intel_dsi->video_mode == BURST_MODE) {
u32 bitrate;
if (mipi_config->target_burst_mode_freq == 0) {
drm_err(display->drm, "Burst mode target is not set\n"); returnfalse;
}
bitrate = intel_dsi_bitrate(intel_dsi);
/* * Sometimes the VBT contains a slightly lower clock, then * the bitrate we have calculated, in this case just replace it * with the calculated bitrate.
*/ if (mipi_config->target_burst_mode_freq < bitrate &&
intel_fuzzy_clock_check(mipi_config->target_burst_mode_freq,
bitrate))
mipi_config->target_burst_mode_freq = bitrate;
if (mipi_config->target_burst_mode_freq < bitrate) {
drm_err(display->drm, "Burst mode freq is less than computed\n"); returnfalse;
}
/* delays in VBT are in unit of 100us, so need to convert * here in ms
* Delay (100us) * 100 /1000 = Delay / 10 (ms) */
intel_dsi->backlight_off_delay = pps->bl_disable_delay / 10;
intel_dsi->backlight_on_delay = pps->bl_enable_delay / 10;
intel_dsi->panel_on_delay = pps->panel_on_delay / 10;
intel_dsi->panel_off_delay = pps->panel_off_delay / 10;
intel_dsi->panel_pwr_cycle_delay = pps->panel_power_cycle_delay / 10;
intel_dsi->i2c_bus_num = -1;
/* a regular driver would get the device in probe */
for_each_dsi_port(port, intel_dsi->ports) {
mipi_dsi_attach(intel_dsi->dsi_hosts[port]->device);
}
returntrue;
}
/* * On some BYT/CHT devs some sequences are incomplete and we need to manually * control some GPIOs. We need to add a GPIO lookup table before we get these. * If the GOP did not initialize the panel (HDMI inserted) we may need to also * change the pinmux for the SoC's PWM0 pin from GPIO to PWM.
*/ staticstruct gpiod_lookup_table pmic_panel_gpio_table = { /* Intel GFX is consumer */
.dev_id = "0000:00:02.0",
.table = { /* Panel EN/DISABLE */
GPIO_LOOKUP("gpio_crystalcove", 94, "panel", GPIO_ACTIVE_HIGH),
{ }
},
};
/* Ensure PWM0 pin is muxed as PWM instead of GPIO */
ret = pinctrl_register_mappings(soc_pwm_pinctrl_map,
ARRAY_SIZE(soc_pwm_pinctrl_map)); if (ret)
drm_err(display->drm, "Failed to register pwm0 pinmux mapping\n");
pinctrl = devm_pinctrl_get_select(display->drm->dev, "soc_pwm0"); if (IS_ERR(pinctrl))
drm_err(display->drm, "Failed to set pinmux to PWM\n");
}
if (gpiod_lookup_table)
gpiod_add_lookup_table(gpiod_lookup_table);
if (want_panel_gpio) {
intel_dsi->gpio_panel = devm_gpiod_get(display->drm->dev, "panel", flags); if (IS_ERR(intel_dsi->gpio_panel)) {
drm_err(display->drm, "Failed to own gpio for panel control\n");
intel_dsi->gpio_panel = NULL;
}
}
if (want_backlight_gpio) {
intel_dsi->gpio_backlight =
devm_gpiod_get(display->drm->dev, "backlight", flags); if (IS_ERR(intel_dsi->gpio_backlight)) {
drm_err(display->drm, "Failed to own gpio for backlight control\n");
intel_dsi->gpio_backlight = NULL;
}
}
if (gpiod_lookup_table)
gpiod_remove_lookup_table(gpiod_lookup_table);
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet)
¤
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.