diff --git a/Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml b/Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml new file mode 100644 index 0000000000000..f29789994b180 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml @@ -0,0 +1,126 @@ +# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/panel-mipi-dbi-spi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MIPI DBI SPI Panel + +maintainers: + - Noralf Trønnes + +description: | + This binding is for display panels using a MIPI DBI compatible controller + in SPI mode. + + The MIPI Alliance Standard for Display Bus Interface defines the electrical + and logical interfaces for display controllers historically used in mobile + phones. The standard defines 4 display architecture types and this binding is + for type 1 which has full frame memory. There are 3 interface types in the + standard and type C is the serial interface. + + The standard defines the following interface signals for type C: + - Power: + - Vdd: Power supply for display module + - Vddi: Logic level supply for interface signals + Combined into one in this binding called: power-supply + - Interface: + - CSx: Chip select + - SCL: Serial clock + - Dout: Serial out + - Din: Serial in + - SDA: Bidrectional in/out + - D/CX: Data/command selection, high=data, low=command + Called dc-gpios in this binding. + - RESX: Reset when low + Called reset-gpios in this binding. + + The type C interface has 3 options: + + - Option 1: 9-bit mode and D/CX as the 9th bit + | Command | the next command or following data | + |<0>|| + + - Option 2: 16-bit mode and D/CX as a 9th bit + | Command or data | + || + + - Option 3: 8-bit mode and D/CX as a separate interface line + | Command or data | + || + + The panel resolution is specified using the panel-timing node properties + hactive (width) and vactive (height). The other mandatory panel-timing + properties should be set to zero except clock-frequency which can be + optionally set to inform about the actual pixel clock frequency. + + If the panel is wired to the controller at an offset specify this using + hback-porch (x-offset) and vback-porch (y-offset). + +allOf: + - $ref: panel-common.yaml# + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + items: + - enum: + - sainsmart18 + - const: panel-mipi-dbi-spi + + write-only: + type: boolean + description: + Controller is not readable (ie. Din (MISO on the SPI interface) is not + wired up). + + dc-gpios: + maxItems: 1 + description: | + Controller data/command selection (D/CX) in 4-line SPI mode. + If not set, the controller is in 3-line SPI mode. + +required: + - compatible + - reg + - panel-timing + +unevaluatedProperties: false + +examples: + - | + #include + + spi { + #address-cells = <1>; + #size-cells = <0>; + + display@0{ + compatible = "sainsmart18", "panel-mipi-dbi-spi"; + reg = <0>; + spi-max-frequency = <40000000>; + + dc-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>; + write-only; + + backlight = <&backlight>; + + width-mm = <35>; + height-mm = <28>; + + panel-timing { + hactive = <160>; + vactive = <128>; + hback-porch = <0>; + vback-porch = <0>; + clock-frequency = <0>; + hfront-porch = <0>; + hsync-len = <0>; + vfront-porch = <0>; + vsync-len = <0>; + }; + }; + }; + +... diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 7bf7f21116966..127e76ee0b2dd 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -241,6 +241,28 @@ Contact: Thomas Zimmermann , Daniel Vetter Level: Advanced +Benchmark and optimize blitting and format-conversion function +-------------------------------------------------------------- + +Drawing to dispay memory quickly is crucial for many applications' +performance. + +On at least x86-64, sys_imageblit() is significantly slower than +cfb_imageblit(), even though both use the same blitting algorithm and +the latter is written for I/O memory. It turns out that cfb_imageblit() +uses movl instructions, while sys_imageblit apparently does not. This +seems to be a problem with gcc's optimizer. DRM's format-conversion +helpers might be subject to similar issues. + +Benchmark and optimize fbdev's sys_() helpers and DRM's format-conversion +helpers. In cases that can be further optimized, maybe implement a different +algorithm. For micro-optimizations, use movl/movq instructions explicitly. +That might possibly require architecture-specific helpers (e.g., storel() +storeq()). + +Contact: Thomas Zimmermann + +Level: Intermediate drm_framebuffer_funcs and drm_mode_config_funcs.fb_create cleanup ----------------------------------------------------------------- @@ -475,8 +497,12 @@ This is a really varied tasks with lots of little bits and pieces: achieved by using an IPI to the local processor. * There's a massive confusion of different panic handlers. DRM fbdev emulation - helpers have one, but on top of that the fbcon code itself also has one. We - need to make sure that they stop fighting over each another. + helpers had their own (long removed), but on top of that the fbcon code itself + also has one. We need to make sure that they stop fighting over each other. + This is worked around by checking ``oops_in_progress`` at various entry points + into the DRM fbdev emulation helpers. A much cleaner approach here would be to + switch fbcon to the `threaded printk support + `_. * ``drm_can_sleep()`` is a mess. It hides real bugs in normal operations and isn't a full solution for panic paths. We need to make sure that it only @@ -488,16 +514,15 @@ This is a really varied tasks with lots of little bits and pieces: even spinlocks (because NMI and hardirq can panic too). We need to either make sure to not call such paths, or trylock everything. Really tricky. -* For the above locking troubles reasons it's pretty much impossible to - attempt a synchronous modeset from panic handlers. The only thing we could - try to achive is an atomic ``set_base`` of the primary plane, and hope that - it shows up. Everything else probably needs to be delayed to some worker or - something else which happens later on. Otherwise it just kills the box - harder, prevent the panic from going out on e.g. netconsole. +* A clean solution would be an entirely separate panic output support in KMS, + bypassing the current fbcon support. See `[PATCH v2 0/3] drm: Add panic handling + `_. -* There's also proposal for a simplied DRM console instead of the full-blown - fbcon and DRM fbdev emulation. Any kind of panic handling tricks should - obviously work for both console, in case we ever get kmslog merged. +* Encoding the actual oops and preceding dmesg in a QR might help with the + dread "important stuff scrolled away" problem. See `[RFC][PATCH] Oops messages + transfer using QR codes + `_ + for some example code that could be reused. Contact: Daniel Vetter diff --git a/MAINTAINERS b/MAINTAINERS index e0ad1bc5b9d45..18d799bb66ecf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6112,6 +6112,14 @@ T: git git://anongit.freedesktop.org/drm/drm-misc F: Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt F: drivers/gpu/drm/tiny/mi0283qt.c +DRM DRIVER FOR MIPI DBI compatible panels +M: Noralf Trønnes +S: Maintained +W: https://github.com/notro/panel-mipi-dbi/wiki +T: git git://anongit.freedesktop.org/drm/drm-misc +F: Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml +F: drivers/gpu/drm/tiny/panel-mipi-dbi.c + DRM DRIVER FOR MSM ADRENO GPU M: Rob Clark M: Sean Paul diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx.h b/drivers/gpu/drm/aspeed/aspeed_gfx.h index 96501152bafac..4e6a442c3886d 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx.h +++ b/drivers/gpu/drm/aspeed/aspeed_gfx.h @@ -12,6 +12,7 @@ struct aspeed_gfx { struct regmap *scu; u32 dac_reg; + u32 int_clr_reg; u32 vga_scratch_reg; u32 throd_val; u32 scan_line_max; diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c index 13f496473b9ea..7780b72de9e80 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c @@ -61,6 +61,7 @@ struct aspeed_gfx_config { u32 dac_reg; /* DAC register in SCU */ + u32 int_clear_reg; /* Interrupt clear register */ u32 vga_scratch_reg; /* VGA scratch register in SCU */ u32 throd_val; /* Default Threshold Seting */ u32 scan_line_max; /* Max memory size of one scan line */ @@ -68,6 +69,7 @@ struct aspeed_gfx_config { static const struct aspeed_gfx_config ast2400_config = { .dac_reg = 0x2c, + .int_clear_reg = 0x60, .vga_scratch_reg = 0x50, .throd_val = CRT_THROD_LOW(0x1e) | CRT_THROD_HIGH(0x12), .scan_line_max = 64, @@ -75,14 +77,24 @@ static const struct aspeed_gfx_config ast2400_config = { static const struct aspeed_gfx_config ast2500_config = { .dac_reg = 0x2c, + .int_clear_reg = 0x60, .vga_scratch_reg = 0x50, .throd_val = CRT_THROD_LOW(0x24) | CRT_THROD_HIGH(0x3c), .scan_line_max = 128, }; +static const struct aspeed_gfx_config ast2600_config = { + .dac_reg = 0xc0, + .int_clear_reg = 0x68, + .vga_scratch_reg = 0x50, + .throd_val = CRT_THROD_LOW(0x50) | CRT_THROD_HIGH(0x70), + .scan_line_max = 128, +}; + static const struct of_device_id aspeed_gfx_match[] = { { .compatible = "aspeed,ast2400-gfx", .data = &ast2400_config }, { .compatible = "aspeed,ast2500-gfx", .data = &ast2500_config }, + { .compatible = "aspeed,ast2600-gfx", .data = &ast2600_config }, { }, }; MODULE_DEVICE_TABLE(of, aspeed_gfx_match); @@ -120,7 +132,7 @@ static irqreturn_t aspeed_gfx_irq_handler(int irq, void *data) if (reg & CRT_CTRL_VERTICAL_INTR_STS) { drm_crtc_handle_vblank(&priv->pipe.crtc); - writel(reg, priv->base + CRT_CTRL1); + writel(reg, priv->base + priv->int_clr_reg); return IRQ_HANDLED; } @@ -148,6 +160,7 @@ static int aspeed_gfx_load(struct drm_device *drm) config = match->data; priv->dac_reg = config->dac_reg; + priv->int_clr_reg = config->int_clear_reg; priv->vga_scratch_reg = config->vga_scratch_reg; priv->throd_val = config->throd_val; priv->scan_line_max = config->scan_line_max; diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 633618bafd75d..31ecf5626f1d9 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -253,6 +253,8 @@ static int anx7625_aux_trans(struct anx7625_data *ctx, u8 op, u32 address, addrm = (address >> 8) & 0xFF; addrh = (address >> 16) & 0xFF; + if (!is_write) + op &= ~DP_AUX_I2C_MOT; cmd = DPCD_CMD(len, op); /* Set command and length */ @@ -2736,8 +2738,8 @@ static int anx7625_i2c_remove(struct i2c_client *client) if (platform->hdcp_workqueue) { cancel_delayed_work(&platform->hdcp_work); - flush_workqueue(platform->workqueue); - destroy_workqueue(platform->workqueue); + flush_workqueue(platform->hdcp_workqueue); + destroy_workqueue(platform->hdcp_workqueue); } if (!platform->pdata.low_power_mode) diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c index d8a15c459b42c..829e1a1446567 100644 --- a/drivers/gpu/drm/bridge/cdns-dsi.c +++ b/drivers/gpu/drm/bridge/cdns-dsi.c @@ -1284,6 +1284,7 @@ static const struct of_device_id cdns_dsi_of_match[] = { { .compatible = "cdns,dsi" }, { }, }; +MODULE_DEVICE_TABLE(of, cdns_dsi_of_match); static struct platform_driver cdns_dsi_platform_driver = { .probe = cdns_dsi_drm_probe, diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index e8f36dca56b33..d9b7f48b99fbf 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -191,7 +191,6 @@ static const struct drm_bridge_funcs chipone_bridge_funcs = { static int chipone_parse_dt(struct chipone *icn) { struct device *dev = icn->dev; - struct drm_panel *panel; int ret; icn->vdd1 = devm_regulator_get_optional(dev, "vdd1"); @@ -227,11 +226,7 @@ static int chipone_parse_dt(struct chipone *icn) return PTR_ERR(icn->enable_gpio); } - ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); - if (ret) - return ret; - - icn->panel_bridge = devm_drm_panel_bridge_add(dev, panel); + icn->panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); if (IS_ERR(icn->panel_bridge)) return PTR_ERR(icn->panel_bridge); diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index fb16a176822d8..f2f101220ade9 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -289,7 +289,7 @@ #define WORD_LENGTH_20BIT 2 #define WORD_LENGTH_24BIT 3 #define DEBUGFS_DIR_NAME "it6505-debugfs" -#define READ_BUFFER_SIZE 200 +#define READ_BUFFER_SIZE 400 /* Vendor option */ #define HDCP_DESIRED 1 @@ -3074,7 +3074,7 @@ static ssize_t receive_timing_debugfs_show(struct file *file, char __user *buf, struct it6505 *it6505 = file->private_data; struct drm_display_mode *vid = &it6505->video_info; u8 read_buf[READ_BUFFER_SIZE]; - u8 *str = read_buf, *end = read_buf + PAGE_SIZE; + u8 *str = read_buf, *end = read_buf + READ_BUFFER_SIZE; ssize_t ret, count; if (!it6505) diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c index 963a6794735f5..d5945501a5ee7 100644 --- a/drivers/gpu/drm/bridge/nwl-dsi.c +++ b/drivers/gpu/drm/bridge/nwl-dsi.c @@ -332,17 +332,13 @@ static int nwl_dsi_config_dpi(struct nwl_dsi *dsi) static int nwl_dsi_init_interrupts(struct nwl_dsi *dsi) { - u32 irq_enable; - - nwl_dsi_write(dsi, NWL_DSI_IRQ_MASK, 0xffffffff); - nwl_dsi_write(dsi, NWL_DSI_IRQ_MASK2, 0x7); - - irq_enable = ~(u32)(NWL_DSI_TX_PKT_DONE_MASK | - NWL_DSI_RX_PKT_HDR_RCVD_MASK | - NWL_DSI_TX_FIFO_OVFLW_MASK | - NWL_DSI_HS_TX_TIMEOUT_MASK); + u32 irq_enable = ~(u32)(NWL_DSI_TX_PKT_DONE_MASK | + NWL_DSI_RX_PKT_HDR_RCVD_MASK | + NWL_DSI_TX_FIFO_OVFLW_MASK | + NWL_DSI_HS_TX_TIMEOUT_MASK); nwl_dsi_write(dsi, NWL_DSI_IRQ_MASK, irq_enable); + nwl_dsi_write(dsi, NWL_DSI_IRQ_MASK2, 0x7); return nwl_dsi_clear_error(dsi); } diff --git a/drivers/gpu/drm/dp/drm_dp.c b/drivers/gpu/drm/dp/drm_dp.c index e159b81800d4a..703972ae14c64 100644 --- a/drivers/gpu/drm/dp/drm_dp.c +++ b/drivers/gpu/drm/dp/drm_dp.c @@ -208,16 +208,6 @@ bool drm_dp_128b132b_link_training_failed(const u8 link_status[DP_LINK_STATUS_SI } EXPORT_SYMBOL(drm_dp_128b132b_link_training_failed); -u8 drm_dp_get_adjust_request_post_cursor(const u8 link_status[DP_LINK_STATUS_SIZE], - unsigned int lane) -{ - unsigned int offset = DP_ADJUST_REQUEST_POST_CURSOR2; - u8 value = dp_link_status(link_status, offset); - - return (value >> (lane << 1)) & 0x3; -} -EXPORT_SYMBOL(drm_dp_get_adjust_request_post_cursor); - static int __8b10b_clock_recovery_delay_us(const struct drm_dp_aux *aux, u8 rd_interval) { if (rd_interval > 4) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index ddcf5c2c8e6a2..3b6d3bdbd0996 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -243,11 +243,36 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *plane_state, struct drm_plane *plane) { + u64 val; + plane_state->plane = plane; plane_state->rotation = DRM_MODE_ROTATE_0; plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE; plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; + + if (plane->color_encoding_property) { + if (!drm_object_property_get_default_value(&plane->base, + plane->color_encoding_property, + &val)) + plane_state->color_encoding = val; + } + + if (plane->color_range_property) { + if (!drm_object_property_get_default_value(&plane->base, + plane->color_range_property, + &val)) + plane_state->color_range = val; + } + + if (plane->zpos_property) { + if (!drm_object_property_get_default_value(&plane->base, + plane->zpos_property, + &val)) { + plane_state->zpos = val; + plane_state->normalized_zpos = val; + } + } } EXPORT_SYMBOL(__drm_atomic_helper_plane_state_reset); diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index 86d9e907c0b21..ba1608effc0fe 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -297,11 +297,26 @@ int drm_object_property_set_value(struct drm_mode_object *obj, } EXPORT_SYMBOL(drm_object_property_set_value); +static int __drm_object_property_get_prop_value(struct drm_mode_object *obj, + struct drm_property *property, + uint64_t *val) +{ + int i; + + for (i = 0; i < obj->properties->count; i++) { + if (obj->properties->properties[i] == property) { + *val = obj->properties->values[i]; + return 0; + } + } + + return -EINVAL; +} + static int __drm_object_property_get_value(struct drm_mode_object *obj, struct drm_property *property, uint64_t *val) { - int i; /* read-only properties bypass atomic mechanism and still store * their value in obj->properties->values[].. mostly to avoid @@ -311,15 +326,7 @@ static int __drm_object_property_get_value(struct drm_mode_object *obj, !(property->flags & DRM_MODE_PROP_IMMUTABLE)) return drm_atomic_get_property(obj, property, val); - for (i = 0; i < obj->properties->count; i++) { - if (obj->properties->properties[i] == property) { - *val = obj->properties->values[i]; - return 0; - } - - } - - return -EINVAL; + return __drm_object_property_get_prop_value(obj, property, val); } /** @@ -348,6 +355,32 @@ int drm_object_property_get_value(struct drm_mode_object *obj, } EXPORT_SYMBOL(drm_object_property_get_value); +/** + * drm_object_property_get_default_value - retrieve the default value of a + * property when in atomic mode. + * @obj: drm mode object to get property value from + * @property: property to retrieve + * @val: storage for the property value + * + * This function retrieves the default state of the given property as passed in + * to drm_object_attach_property + * + * Only atomic drivers should call this function directly, as for non-atomic + * drivers it will return the current value. + * + * Returns: + * Zero on success, error code on failure. + */ +int drm_object_property_get_default_value(struct drm_mode_object *obj, + struct drm_property *property, + uint64_t *val) +{ + WARN_ON(!drm_drv_uses_atomic_modeset(property->dev)); + + return __drm_object_property_get_prop_value(obj, property, val); +} +EXPORT_SYMBOL(drm_object_property_get_default_value); + /* helper for getconnector and getproperties ioctls */ int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, uint32_t __user *prop_ptr, diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 96b13e36293c3..3f819c7a021b0 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -35,6 +35,7 @@ #include #include +#include