Commit c9e9ce0b authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-next-2022-03-03' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

drm-misc-next for v5.18:

UAPI Changes:

Cross-subsystem Changes:
- Improve performance of some fbdev ops, in some cases up to 6x faster.

Core Changes:
- Some small DP fixes.
- Find panels in subnodes of OF devices, and add of_get_drm_panel_display_mode
  to retrieve mode.
- Add drm_object_property_get_default_value and use it for resetting
  zpos in plane state reset, removing the need for individual drivers
  to do it.
- Same for color encoding and color range props.
- Update panic handling todo doc.
- Add todo that format conversion helpers should be sped up similarly to fbdev ops.

Driver Changes:
- Add panel orientation property to simpledrm for quirked panels.
- Assorted small fixes to tiny/repaper, nouveau, stm, omap, ssd130x.
- Add crc support to stm/ltdc.
- Add MIPI DBI compatible SPI driver
- Assorted small fixes to tiny panels and bridge drivers.
- Add AST2600 support to aspeed.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/48fabd78-ade9-f80b-c724-13726c7be69e@linux.intel.com
parents f298a2b9 701920ca
# 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 <noralf@tronnes.org>
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><D7><D6><D5><D4><D3><D2><D1><D0>|<D/CX><D7><D6><D5><D4><D3><D2><D1><D0>|
- Option 2: 16-bit mode and D/CX as a 9th bit
| Command or data |
|<X><X><X><X><X><X><X><D/CX><D7><D6><D5><D4><D3><D2><D1><D0>|
- Option 3: 8-bit mode and D/CX as a separate interface line
| Command or data |
|<D7><D6><D5><D4><D3><D2><D1><D0>|
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 <dt-bindings/gpio/gpio.h>
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>;
};
};
};
...
...@@ -241,6 +241,28 @@ Contact: Thomas Zimmermann <tzimmermann@suse.de>, Daniel Vetter ...@@ -241,6 +241,28 @@ Contact: Thomas Zimmermann <tzimmermann@suse.de>, Daniel Vetter
Level: Advanced 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 <tzimmermann@suse.de>
Level: Intermediate
drm_framebuffer_funcs and drm_mode_config_funcs.fb_create cleanup 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: ...@@ -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. achieved by using an IPI to the local processor.
* There's a massive confusion of different panic handlers. DRM fbdev emulation * 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 helpers had their own (long removed), but on top of that the fbcon code itself
need to make sure that they stop fighting over each another. 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
<https://lwn.net/Articles/800946/>`_.
* ``drm_can_sleep()`` is a mess. It hides real bugs in normal operations and * ``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 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: ...@@ -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 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. make sure to not call such paths, or trylock everything. Really tricky.
* For the above locking troubles reasons it's pretty much impossible to * A clean solution would be an entirely separate panic output support in KMS,
attempt a synchronous modeset from panic handlers. The only thing we could bypassing the current fbcon support. See `[PATCH v2 0/3] drm: Add panic handling
try to achive is an atomic ``set_base`` of the primary plane, and hope that <https://lore.kernel.org/dri-devel/20190311174218.51899-1-noralf@tronnes.org/>`_.
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.
* There's also proposal for a simplied DRM console instead of the full-blown * Encoding the actual oops and preceding dmesg in a QR might help with the
fbcon and DRM fbdev emulation. Any kind of panic handling tricks should dread "important stuff scrolled away" problem. See `[RFC][PATCH] Oops messages
obviously work for both console, in case we ever get kmslog merged. transfer using QR codes
<https://lore.kernel.org/lkml/1446217392-11981-1-git-send-email-alexandru.murtaza@intel.com/>`_
for some example code that could be reused.
Contact: Daniel Vetter Contact: Daniel Vetter
......
...@@ -6112,6 +6112,14 @@ T: git git://anongit.freedesktop.org/drm/drm-misc ...@@ -6112,6 +6112,14 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
F: Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt F: Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt
F: drivers/gpu/drm/tiny/mi0283qt.c F: drivers/gpu/drm/tiny/mi0283qt.c
DRM DRIVER FOR MIPI DBI compatible panels
M: Noralf Trønnes <noralf@tronnes.org>
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 DRM DRIVER FOR MSM ADRENO GPU
M: Rob Clark <robdclark@gmail.com> M: Rob Clark <robdclark@gmail.com>
M: Sean Paul <sean@poorly.run> M: Sean Paul <sean@poorly.run>
......
...@@ -12,6 +12,7 @@ struct aspeed_gfx { ...@@ -12,6 +12,7 @@ struct aspeed_gfx {
struct regmap *scu; struct regmap *scu;
u32 dac_reg; u32 dac_reg;
u32 int_clr_reg;
u32 vga_scratch_reg; u32 vga_scratch_reg;
u32 throd_val; u32 throd_val;
u32 scan_line_max; u32 scan_line_max;
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
struct aspeed_gfx_config { struct aspeed_gfx_config {
u32 dac_reg; /* DAC register in SCU */ u32 dac_reg; /* DAC register in SCU */
u32 int_clear_reg; /* Interrupt clear register */
u32 vga_scratch_reg; /* VGA scratch register in SCU */ u32 vga_scratch_reg; /* VGA scratch register in SCU */
u32 throd_val; /* Default Threshold Seting */ u32 throd_val; /* Default Threshold Seting */
u32 scan_line_max; /* Max memory size of one scan line */ u32 scan_line_max; /* Max memory size of one scan line */
...@@ -68,6 +69,7 @@ struct aspeed_gfx_config { ...@@ -68,6 +69,7 @@ struct aspeed_gfx_config {
static const struct aspeed_gfx_config ast2400_config = { static const struct aspeed_gfx_config ast2400_config = {
.dac_reg = 0x2c, .dac_reg = 0x2c,
.int_clear_reg = 0x60,
.vga_scratch_reg = 0x50, .vga_scratch_reg = 0x50,
.throd_val = CRT_THROD_LOW(0x1e) | CRT_THROD_HIGH(0x12), .throd_val = CRT_THROD_LOW(0x1e) | CRT_THROD_HIGH(0x12),
.scan_line_max = 64, .scan_line_max = 64,
...@@ -75,14 +77,24 @@ static const struct aspeed_gfx_config ast2400_config = { ...@@ -75,14 +77,24 @@ static const struct aspeed_gfx_config ast2400_config = {
static const struct aspeed_gfx_config ast2500_config = { static const struct aspeed_gfx_config ast2500_config = {
.dac_reg = 0x2c, .dac_reg = 0x2c,
.int_clear_reg = 0x60,
.vga_scratch_reg = 0x50, .vga_scratch_reg = 0x50,
.throd_val = CRT_THROD_LOW(0x24) | CRT_THROD_HIGH(0x3c), .throd_val = CRT_THROD_LOW(0x24) | CRT_THROD_HIGH(0x3c),
.scan_line_max = 128, .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[] = { static const struct of_device_id aspeed_gfx_match[] = {
{ .compatible = "aspeed,ast2400-gfx", .data = &ast2400_config }, { .compatible = "aspeed,ast2400-gfx", .data = &ast2400_config },
{ .compatible = "aspeed,ast2500-gfx", .data = &ast2500_config }, { .compatible = "aspeed,ast2500-gfx", .data = &ast2500_config },
{ .compatible = "aspeed,ast2600-gfx", .data = &ast2600_config },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, aspeed_gfx_match); MODULE_DEVICE_TABLE(of, aspeed_gfx_match);
...@@ -120,7 +132,7 @@ static irqreturn_t aspeed_gfx_irq_handler(int irq, void *data) ...@@ -120,7 +132,7 @@ static irqreturn_t aspeed_gfx_irq_handler(int irq, void *data)
if (reg & CRT_CTRL_VERTICAL_INTR_STS) { if (reg & CRT_CTRL_VERTICAL_INTR_STS) {
drm_crtc_handle_vblank(&priv->pipe.crtc); drm_crtc_handle_vblank(&priv->pipe.crtc);
writel(reg, priv->base + CRT_CTRL1); writel(reg, priv->base + priv->int_clr_reg);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -148,6 +160,7 @@ static int aspeed_gfx_load(struct drm_device *drm) ...@@ -148,6 +160,7 @@ static int aspeed_gfx_load(struct drm_device *drm)
config = match->data; config = match->data;
priv->dac_reg = config->dac_reg; priv->dac_reg = config->dac_reg;
priv->int_clr_reg = config->int_clear_reg;
priv->vga_scratch_reg = config->vga_scratch_reg; priv->vga_scratch_reg = config->vga_scratch_reg;
priv->throd_val = config->throd_val; priv->throd_val = config->throd_val;
priv->scan_line_max = config->scan_line_max; priv->scan_line_max = config->scan_line_max;
......
...@@ -253,6 +253,8 @@ static int anx7625_aux_trans(struct anx7625_data *ctx, u8 op, u32 address, ...@@ -253,6 +253,8 @@ static int anx7625_aux_trans(struct anx7625_data *ctx, u8 op, u32 address,
addrm = (address >> 8) & 0xFF; addrm = (address >> 8) & 0xFF;
addrh = (address >> 16) & 0xFF; addrh = (address >> 16) & 0xFF;
if (!is_write)
op &= ~DP_AUX_I2C_MOT;
cmd = DPCD_CMD(len, op); cmd = DPCD_CMD(len, op);
/* Set command and length */ /* Set command and length */
...@@ -2736,8 +2738,8 @@ static int anx7625_i2c_remove(struct i2c_client *client) ...@@ -2736,8 +2738,8 @@ static int anx7625_i2c_remove(struct i2c_client *client)
if (platform->hdcp_workqueue) { if (platform->hdcp_workqueue) {
cancel_delayed_work(&platform->hdcp_work); cancel_delayed_work(&platform->hdcp_work);
flush_workqueue(platform->workqueue); flush_workqueue(platform->hdcp_workqueue);
destroy_workqueue(platform->workqueue); destroy_workqueue(platform->hdcp_workqueue);
} }
if (!platform->pdata.low_power_mode) if (!platform->pdata.low_power_mode)
......
...@@ -1284,6 +1284,7 @@ static const struct of_device_id cdns_dsi_of_match[] = { ...@@ -1284,6 +1284,7 @@ static const struct of_device_id cdns_dsi_of_match[] = {
{ .compatible = "cdns,dsi" }, { .compatible = "cdns,dsi" },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, cdns_dsi_of_match);
static struct platform_driver cdns_dsi_platform_driver = { static struct platform_driver cdns_dsi_platform_driver = {
.probe = cdns_dsi_drm_probe, .probe = cdns_dsi_drm_probe,
......
...@@ -191,7 +191,6 @@ static const struct drm_bridge_funcs chipone_bridge_funcs = { ...@@ -191,7 +191,6 @@ static const struct drm_bridge_funcs chipone_bridge_funcs = {
static int chipone_parse_dt(struct chipone *icn) static int chipone_parse_dt(struct chipone *icn)
{ {
struct device *dev = icn->dev; struct device *dev = icn->dev;
struct drm_panel *panel;
int ret; int ret;
icn->vdd1 = devm_regulator_get_optional(dev, "vdd1"); icn->vdd1 = devm_regulator_get_optional(dev, "vdd1");
...@@ -227,11 +226,7 @@ static int chipone_parse_dt(struct chipone *icn) ...@@ -227,11 +226,7 @@ static int chipone_parse_dt(struct chipone *icn)
return PTR_ERR(icn->enable_gpio); return PTR_ERR(icn->enable_gpio);
} }
ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); icn->panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
if (ret)
return ret;
icn->panel_bridge = devm_drm_panel_bridge_add(dev, panel);
if (IS_ERR(icn->panel_bridge)) if (IS_ERR(icn->panel_bridge))
return PTR_ERR(icn->panel_bridge); return PTR_ERR(icn->panel_bridge);
......
...@@ -289,7 +289,7 @@ ...@@ -289,7 +289,7 @@
#define WORD_LENGTH_20BIT 2 #define WORD_LENGTH_20BIT 2
#define WORD_LENGTH_24BIT 3 #define WORD_LENGTH_24BIT 3
#define DEBUGFS_DIR_NAME "it6505-debugfs" #define DEBUGFS_DIR_NAME "it6505-debugfs"
#define READ_BUFFER_SIZE 200 #define READ_BUFFER_SIZE 400
/* Vendor option */ /* Vendor option */
#define HDCP_DESIRED 1 #define HDCP_DESIRED 1
...@@ -3074,7 +3074,7 @@ static ssize_t receive_timing_debugfs_show(struct file *file, char __user *buf, ...@@ -3074,7 +3074,7 @@ static ssize_t receive_timing_debugfs_show(struct file *file, char __user *buf,
struct it6505 *it6505 = file->private_data; struct it6505 *it6505 = file->private_data;
struct drm_display_mode *vid = &it6505->video_info; struct drm_display_mode *vid = &it6505->video_info;
u8 read_buf[READ_BUFFER_SIZE]; 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; ssize_t ret, count;
if (!it6505) if (!it6505)
......
...@@ -332,17 +332,13 @@ static int nwl_dsi_config_dpi(struct nwl_dsi *dsi) ...@@ -332,17 +332,13 @@ static int nwl_dsi_config_dpi(struct nwl_dsi *dsi)
static int nwl_dsi_init_interrupts(struct nwl_dsi *dsi) static int nwl_dsi_init_interrupts(struct nwl_dsi *dsi)
{ {
u32 irq_enable; u32 irq_enable = ~(u32)(NWL_DSI_TX_PKT_DONE_MASK |
NWL_DSI_RX_PKT_HDR_RCVD_MASK |
nwl_dsi_write(dsi, NWL_DSI_IRQ_MASK, 0xffffffff); NWL_DSI_TX_FIFO_OVFLW_MASK |
nwl_dsi_write(dsi, NWL_DSI_IRQ_MASK2, 0x7); NWL_DSI_HS_TX_TIMEOUT_MASK);
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_MASK, irq_enable);
nwl_dsi_write(dsi, NWL_DSI_IRQ_MASK2, 0x7);
return nwl_dsi_clear_error(dsi); return nwl_dsi_clear_error(dsi);
} }
......
...@@ -208,16 +208,6 @@ bool drm_dp_128b132b_link_training_failed(const u8 link_status[DP_LINK_STATUS_SI ...@@ -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); 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) static int __8b10b_clock_recovery_delay_us(const struct drm_dp_aux *aux, u8 rd_interval)
{ {
if (rd_interval > 4) if (rd_interval > 4)
......
...@@ -243,11 +243,36 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); ...@@ -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, void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *plane_state,
struct drm_plane *plane) struct drm_plane *plane)
{ {
u64 val;
plane_state->plane = plane; plane_state->plane = plane;
plane_state->rotation = DRM_MODE_ROTATE_0; plane_state->rotation = DRM_MODE_ROTATE_0;
plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE; plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE;
plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; 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); EXPORT_SYMBOL(__drm_atomic_helper_plane_state_reset);
......
...@@ -297,11 +297,26 @@ int drm_object_property_set_value(struct drm_mode_object *obj, ...@@ -297,11 +297,26 @@ int drm_object_property_set_value(struct drm_mode_object *obj,
} }
EXPORT_SYMBOL(drm_object_property_set_value); 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, static int __drm_object_property_get_value(struct drm_mode_object *obj,
struct drm_property *property, struct drm_property *property,
uint64_t *val) uint64_t *val)
{ {
int i;
/* read-only properties bypass atomic mechanism and still store /* read-only properties bypass atomic mechanism and still store
* their value in obj->properties->values[].. mostly to avoid * 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, ...@@ -311,15 +326,7 @@ static int __drm_object_property_get_value(struct drm_mode_object *obj,
!(property->flags & DRM_MODE_PROP_IMMUTABLE)) !(property->flags & DRM_MODE_PROP_IMMUTABLE))
return drm_atomic_get_property(obj, property, val); return drm_atomic_get_property(obj, property, val);
for (i = 0; i < obj->properties->count; i++) { return __drm_object_property_get_prop_value(obj, property, val);
if (obj->properties->properties[i] == property) {
*val = obj->properties->values[i];
return 0;
}
}
return -EINVAL;
} }
/** /**
...@@ -348,6 +355,32 @@ int drm_object_property_get_value(struct drm_mode_object *obj, ...@@ -348,6 +355,32 @@ int drm_object_property_get_value(struct drm_mode_object *obj,
} }
EXPORT_SYMBOL(drm_object_property_get_value); 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 */ /* helper for getconnector and getproperties ioctls */
int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
uint32_t __user *prop_ptr, uint32_t __user *prop_ptr,
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/list_sort.h> #include <linux/list_sort.h>
#include <linux/export.h> #include <linux/export.h>
#include <video/of_display_timing.h>
#include <video/of_videomode.h> #include <video/of_videomode.h>
#include <video/videomode.h> #include <video/videomode.h>
...@@ -127,7 +128,7 @@ EXPORT_SYMBOL(drm_mode_probed_add); ...@@ -127,7 +128,7 @@ EXPORT_SYMBOL(drm_mode_probed_add);
* according to the hdisplay, vdisplay, vrefresh. * according to the hdisplay, vdisplay, vrefresh.
* It is based from the VESA(TM) Coordinated Video Timing Generator by * It is based from the VESA(TM) Coordinated Video Timing Generator by
* Graham Loveridge April 9, 2003 available at * Graham Loveridge April 9, 2003 available at
* http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls
* *
* And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c. * And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c.
* What I have done is to translate it by using integer calculation. * What I have done is to translate it by using integer calculation.
...@@ -727,6 +728,54 @@ int of_get_drm_display_mode(struct device_node *np, ...@@ -727,6 +728,54 @@ int of_get_drm_display_mode(struct device_node *np,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(of_get_drm_display_mode); EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
/**
* of_get_drm_panel_display_mode - get a panel-timing drm_display_mode from devicetree
* @np: device_node with the panel-timing specification
* @dmode: will be set to the return value
* @bus_flags: information about pixelclk, sync and DE polarity
*
* The Device Tree properties width-mm and height-mm will be read and set on
* the display mode if they are present.
*
* Returns:
* Zero on success, negative error code on failure.
*/
int of_get_drm_panel_display_mode(struct device_node *np,
struct drm_display_mode *dmode, u32 *bus_flags)
{
u32 width_mm = 0, height_mm = 0;
struct display_timing timing;
struct videomode vm;
int ret;
ret = of_get_display_timing(np, "panel-timing", &timing);
if (ret)
return ret;
videomode_from_timing(&timing, &vm);
memset(dmode, 0, sizeof(*dmode));
drm_display_mode_from_videomode(&vm, dmode);
if (bus_flags)
drm_bus_flags_from_videomode(&vm, bus_flags);
ret = of_property_read_u32(np, "width-mm", &width_mm);
if (ret && ret != -EINVAL)
return ret;
ret = of_property_read_u32(np, "height-mm", &height_mm);
if (ret && ret != -EINVAL)
return ret;
dmode->width_mm = width_mm;
dmode->height_mm = height_mm;
drm_mode_debug_printmodeline(dmode);
return 0;
}
EXPORT_SYMBOL_GPL(of_get_drm_panel_display_mode);
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
#endif /* CONFIG_VIDEOMODE_HELPERS */ #endif /* CONFIG_VIDEOMODE_HELPERS */
......
...@@ -249,6 +249,21 @@ int drm_of_find_panel_or_bridge(const struct device_node *np, ...@@ -249,6 +249,21 @@ int drm_of_find_panel_or_bridge(const struct device_node *np,
if (panel) if (panel)
*panel = NULL; *panel = NULL;
/**
* Devices can also be child nodes when we also control that device
* through the upstream device (ie, MIPI-DCS for a MIPI-DSI device).
*
* Lookup for a child node of the given parent that isn't either port
* or ports.
*/
for_each_available_child_of_node(np, remote) {
if (of_node_name_eq(remote, "port") ||
of_node_name_eq(remote, "ports"))
continue;
goto of_find_panel_or_bridge;
}
/* /*
* of_graph_get_remote_node() produces a noisy error message if port * of_graph_get_remote_node() produces a noisy error message if port
* node isn't found and the absence of the port is a legit case here, * node isn't found and the absence of the port is a legit case here,
...@@ -259,6 +274,8 @@ int drm_of_find_panel_or_bridge(const struct device_node *np, ...@@ -259,6 +274,8 @@ int drm_of_find_panel_or_bridge(const struct device_node *np,
return -ENODEV; return -ENODEV;
remote = of_graph_get_remote_node(np, port, endpoint); remote = of_graph_get_remote_node(np, port, endpoint);
of_find_panel_or_bridge:
if (!remote) if (!remote)
return -ENODEV; return -ENODEV;
......
...@@ -48,6 +48,8 @@ static void mdp5_plane_destroy(struct drm_plane *plane) ...@@ -48,6 +48,8 @@ static void mdp5_plane_destroy(struct drm_plane *plane)
static void mdp5_plane_install_properties(struct drm_plane *plane, static void mdp5_plane_install_properties(struct drm_plane *plane,
struct drm_mode_object *obj) struct drm_mode_object *obj)
{ {
unsigned int zpos;
drm_plane_create_rotation_property(plane, drm_plane_create_rotation_property(plane,
DRM_MODE_ROTATE_0, DRM_MODE_ROTATE_0,
DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_0 |
...@@ -59,7 +61,12 @@ static void mdp5_plane_install_properties(struct drm_plane *plane, ...@@ -59,7 +61,12 @@ static void mdp5_plane_install_properties(struct drm_plane *plane,
BIT(DRM_MODE_BLEND_PIXEL_NONE) | BIT(DRM_MODE_BLEND_PIXEL_NONE) |
BIT(DRM_MODE_BLEND_PREMULTI) | BIT(DRM_MODE_BLEND_PREMULTI) |
BIT(DRM_MODE_BLEND_COVERAGE)); BIT(DRM_MODE_BLEND_COVERAGE));
drm_plane_create_zpos_property(plane, 1, 1, 255);
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
zpos = STAGE_BASE;
else
zpos = STAGE0 + drm_plane_index(plane);
drm_plane_create_zpos_property(plane, zpos, 1, 255);
} }
static void static void
...@@ -91,13 +98,6 @@ static void mdp5_plane_reset(struct drm_plane *plane) ...@@ -91,13 +98,6 @@ static void mdp5_plane_reset(struct drm_plane *plane)
kfree(to_mdp5_plane_state(plane->state)); kfree(to_mdp5_plane_state(plane->state));
mdp5_state = kzalloc(sizeof(*mdp5_state), GFP_KERNEL); mdp5_state = kzalloc(sizeof(*mdp5_state), GFP_KERNEL);
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
mdp5_state->base.zpos = STAGE_BASE;
else
mdp5_state->base.zpos = STAGE0 + drm_plane_index(plane);
mdp5_state->base.normalized_zpos = mdp5_state->base.zpos;
__drm_atomic_helper_plane_reset(plane, &mdp5_state->base); __drm_atomic_helper_plane_reset(plane, &mdp5_state->base);
} }
......
...@@ -635,8 +635,6 @@ nv50_wndw_reset(struct drm_plane *plane) ...@@ -635,8 +635,6 @@ nv50_wndw_reset(struct drm_plane *plane)
plane->funcs->atomic_destroy_state(plane, plane->state); plane->funcs->atomic_destroy_state(plane, plane->state);
__drm_atomic_helper_plane_reset(plane, &asyw->state); __drm_atomic_helper_plane_reset(plane, &asyw->state);
plane->state->zpos = nv50_wndw_zpos_default(plane);
plane->state->normalized_zpos = nv50_wndw_zpos_default(plane);
} }
static void static void
......
This diff is collapsed.
...@@ -403,7 +403,6 @@ void omap_plane_install_properties(struct drm_plane *plane, ...@@ -403,7 +403,6 @@ void omap_plane_install_properties(struct drm_plane *plane,
static void omap_plane_reset(struct drm_plane *plane) static void omap_plane_reset(struct drm_plane *plane)
{ {
struct omap_plane *omap_plane = to_omap_plane(plane);
struct omap_plane_state *omap_state; struct omap_plane_state *omap_state;
if (plane->state) if (plane->state)
...@@ -414,15 +413,6 @@ static void omap_plane_reset(struct drm_plane *plane) ...@@ -414,15 +413,6 @@ static void omap_plane_reset(struct drm_plane *plane)
return; return;
__drm_atomic_helper_plane_reset(plane, &omap_state->base); __drm_atomic_helper_plane_reset(plane, &omap_state->base);
/*
* Set the zpos default depending on whether we are a primary or overlay
* plane.
*/
plane->state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY
? 0 : omap_plane->id;
plane->state->color_encoding = DRM_COLOR_YCBCR_BT601;
plane->state->color_range = DRM_COLOR_YCBCR_FULL_RANGE;
} }
static struct drm_plane_state * static struct drm_plane_state *
...@@ -533,6 +523,7 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, ...@@ -533,6 +523,7 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
unsigned int num_planes = dispc_get_num_ovls(priv->dispc); unsigned int num_planes = dispc_get_num_ovls(priv->dispc);
struct drm_plane *plane; struct drm_plane *plane;
struct omap_plane *omap_plane; struct omap_plane *omap_plane;
unsigned int zpos;
int ret; int ret;
u32 nformats; u32 nformats;
const u32 *formats; const u32 *formats;
...@@ -564,7 +555,16 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, ...@@ -564,7 +555,16 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
drm_plane_helper_add(plane, &omap_plane_helper_funcs); drm_plane_helper_add(plane, &omap_plane_helper_funcs);
omap_plane_install_properties(plane, &plane->base); omap_plane_install_properties(plane, &plane->base);
drm_plane_create_zpos_property(plane, 0, 0, num_planes - 1);
/*
* Set the zpos default depending on whether we are a primary or overlay
* plane.
*/
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
zpos = 0;
else
zpos = omap_plane->id;
drm_plane_create_zpos_property(plane, zpos, 0, num_planes - 1);
drm_plane_create_alpha_property(plane); drm_plane_create_alpha_property(plane);
drm_plane_create_blend_mode_property(plane, BIT(DRM_MODE_BLEND_PREMULTI) | drm_plane_create_blend_mode_property(plane, BIT(DRM_MODE_BLEND_PREMULTI) |
BIT(DRM_MODE_BLEND_COVERAGE)); BIT(DRM_MODE_BLEND_COVERAGE));
......
...@@ -3058,6 +3058,7 @@ static const struct drm_display_mode rocktech_rk101ii01d_ct_mode = { ...@@ -3058,6 +3058,7 @@ static const struct drm_display_mode rocktech_rk101ii01d_ct_mode = {
static const struct panel_desc rocktech_rk101ii01d_ct = { static const struct panel_desc rocktech_rk101ii01d_ct = {
.modes = &rocktech_rk101ii01d_ct_mode, .modes = &rocktech_rk101ii01d_ct_mode,
.bpc = 8,
.num_modes = 1, .num_modes = 1,
.size = { .size = {
.width = 217, .width = 217,
......
...@@ -562,7 +562,7 @@ static int panfrost_probe(struct platform_device *pdev) ...@@ -562,7 +562,7 @@ static int panfrost_probe(struct platform_device *pdev)
pfdev->coherent = device_get_dma_attr(&pdev->dev) == DEV_DMA_COHERENT; pfdev->coherent = device_get_dma_attr(&pdev->dev) == DEV_DMA_COHERENT;
/* Allocate and initialze the DRM device. */ /* Allocate and initialize the DRM device. */
ddev = drm_dev_alloc(&panfrost_drm_driver, &pdev->dev); ddev = drm_dev_alloc(&panfrost_drm_driver, &pdev->dev);
if (IS_ERR(ddev)) if (IS_ERR(ddev))
return PTR_ERR(ddev); return PTR_ERR(ddev);
......
/* SPDX-License-Identifier: GPL-2.0 */ // SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2019 Arm Ltd. /* Copyright (C) 2019 Arm Ltd.
* *
* Based on msm_gem_freedreno.c: * Based on msm_gem_freedreno.c:
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
*/ */
enum panfrost_hw_issue { enum panfrost_hw_issue {
/* Need way to guarantee that all previously-translated memory accesses /* Need way to guarantee that all previously-translated memory accesses
* are commited */ * are committed */
HW_ISSUE_6367, HW_ISSUE_6367,
/* On job complete with non-done the cache is not flushed */ /* On job complete with non-done the cache is not flushed */
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
/* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */ /* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
#include <drm/panfrost_drm.h> #include <drm/panfrost_drm.h>
......
...@@ -293,7 +293,7 @@ ...@@ -293,7 +293,7 @@
#define AS_FAULTADDRESS_LO(as) (MMU_AS(as) + 0x20) /* (RO) Fault Address for address space n, low word */ #define AS_FAULTADDRESS_LO(as) (MMU_AS(as) + 0x20) /* (RO) Fault Address for address space n, low word */
#define AS_FAULTADDRESS_HI(as) (MMU_AS(as) + 0x24) /* (RO) Fault Address for address space n, high word */ #define AS_FAULTADDRESS_HI(as) (MMU_AS(as) + 0x24) /* (RO) Fault Address for address space n, high word */
#define AS_STATUS(as) (MMU_AS(as) + 0x28) /* (RO) Status flags for address space n */ #define AS_STATUS(as) (MMU_AS(as) + 0x28) /* (RO) Status flags for address space n */
/* Additional Bifrost AS regsiters */ /* Additional Bifrost AS registers */
#define AS_TRANSCFG_LO(as) (MMU_AS(as) + 0x30) /* (RW) Translation table configuration for address space n, low word */ #define AS_TRANSCFG_LO(as) (MMU_AS(as) + 0x30) /* (RW) Translation table configuration for address space n, low word */
#define AS_TRANSCFG_HI(as) (MMU_AS(as) + 0x34) /* (RW) Translation table configuration for address space n, high word */ #define AS_TRANSCFG_HI(as) (MMU_AS(as) + 0x34) /* (RW) Translation table configuration for address space n, high word */
#define AS_FAULTEXTRA_LO(as) (MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */ #define AS_FAULTEXTRA_LO(as) (MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
......
...@@ -704,7 +704,6 @@ static void rcar_du_plane_reset(struct drm_plane *plane) ...@@ -704,7 +704,6 @@ static void rcar_du_plane_reset(struct drm_plane *plane)
state->hwindex = -1; state->hwindex = -1;
state->source = RCAR_DU_PLANE_MEMORY; state->source = RCAR_DU_PLANE_MEMORY;
state->colorkey = RCAR_DU_COLORKEY_NONE; state->colorkey = RCAR_DU_COLORKEY_NONE;
state->state.zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
} }
static int rcar_du_plane_atomic_set_property(struct drm_plane *plane, static int rcar_du_plane_atomic_set_property(struct drm_plane *plane,
......
...@@ -353,7 +353,6 @@ static void rcar_du_vsp_plane_reset(struct drm_plane *plane) ...@@ -353,7 +353,6 @@ static void rcar_du_vsp_plane_reset(struct drm_plane *plane)
return; return;
__drm_atomic_helper_plane_reset(plane, &state->state); __drm_atomic_helper_plane_reset(plane, &state->state);
state->state.zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
} }
static const struct drm_plane_funcs rcar_du_vsp_plane_funcs = { static const struct drm_plane_funcs rcar_du_vsp_plane_funcs = {
......
...@@ -579,7 +579,7 @@ static const struct drm_simple_display_pipe_funcs ssd130x_pipe_funcs = { ...@@ -579,7 +579,7 @@ static const struct drm_simple_display_pipe_funcs ssd130x_pipe_funcs = {
static int ssd130x_connector_get_modes(struct drm_connector *connector) static int ssd130x_connector_get_modes(struct drm_connector *connector)
{ {
struct ssd130x_device *ssd130x = drm_to_ssd130x(connector->dev); struct ssd130x_device *ssd130x = drm_to_ssd130x(connector->dev);
struct drm_display_mode *mode = &ssd130x->mode; struct drm_display_mode *mode;
struct device *dev = ssd130x->dev; struct device *dev = ssd130x->dev;
mode = drm_mode_duplicate(connector->dev, &ssd130x->mode); mode = drm_mode_duplicate(connector->dev, &ssd130x->mode);
......
...@@ -351,7 +351,7 @@ static const struct drm_plane_funcs sti_cursor_plane_helpers_funcs = { ...@@ -351,7 +351,7 @@ static const struct drm_plane_funcs sti_cursor_plane_helpers_funcs = {
.update_plane = drm_atomic_helper_update_plane, .update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane, .disable_plane = drm_atomic_helper_disable_plane,
.destroy = drm_plane_cleanup, .destroy = drm_plane_cleanup,
.reset = sti_plane_reset, .reset = drm_atomic_helper_plane_reset,
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
.late_register = sti_cursor_late_register, .late_register = sti_cursor_late_register,
......
...@@ -905,7 +905,7 @@ static const struct drm_plane_funcs sti_gdp_plane_helpers_funcs = { ...@@ -905,7 +905,7 @@ static const struct drm_plane_funcs sti_gdp_plane_helpers_funcs = {
.update_plane = drm_atomic_helper_update_plane, .update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane, .disable_plane = drm_atomic_helper_disable_plane,
.destroy = drm_plane_cleanup, .destroy = drm_plane_cleanup,
.reset = sti_plane_reset, .reset = drm_atomic_helper_plane_reset,
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
.late_register = sti_gdp_late_register, .late_register = sti_gdp_late_register,
......
...@@ -1283,7 +1283,7 @@ static const struct drm_plane_funcs sti_hqvdp_plane_helpers_funcs = { ...@@ -1283,7 +1283,7 @@ static const struct drm_plane_funcs sti_hqvdp_plane_helpers_funcs = {
.update_plane = drm_atomic_helper_update_plane, .update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane, .disable_plane = drm_atomic_helper_disable_plane,
.destroy = drm_plane_cleanup, .destroy = drm_plane_cleanup,
.reset = sti_plane_reset, .reset = drm_atomic_helper_plane_reset,
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
.late_register = sti_hqvdp_late_register, .late_register = sti_hqvdp_late_register,
......
...@@ -112,12 +112,6 @@ static int sti_plane_get_default_zpos(enum drm_plane_type type) ...@@ -112,12 +112,6 @@ static int sti_plane_get_default_zpos(enum drm_plane_type type)
return 0; return 0;
} }
void sti_plane_reset(struct drm_plane *plane)
{
drm_atomic_helper_plane_reset(plane);
plane->state->zpos = sti_plane_get_default_zpos(plane->type);
}
static void sti_plane_attach_zorder_property(struct drm_plane *drm_plane, static void sti_plane_attach_zorder_property(struct drm_plane *drm_plane,
enum drm_plane_type type) enum drm_plane_type type)
{ {
......
...@@ -81,5 +81,4 @@ void sti_plane_update_fps(struct sti_plane *plane, ...@@ -81,5 +81,4 @@ void sti_plane_update_fps(struct sti_plane *plane,
void sti_plane_init_property(struct sti_plane *plane, void sti_plane_init_property(struct sti_plane *plane,
enum drm_plane_type type); enum drm_plane_type type);
void sti_plane_reset(struct drm_plane *plane);
#endif #endif
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
#define LTDC_CPSR 0x0044 /* Current Position Status */ #define LTDC_CPSR 0x0044 /* Current Position Status */
#define LTDC_CDSR 0x0048 /* Current Display Status */ #define LTDC_CDSR 0x0048 /* Current Display Status */
#define LTDC_EDCR 0x0060 /* External Display Control */ #define LTDC_EDCR 0x0060 /* External Display Control */
#define LTDC_CCRCR 0x007C /* Computed CRC value */
#define LTDC_FUT 0x0090 /* Fifo underrun Threshold */ #define LTDC_FUT 0x0090 /* Fifo underrun Threshold */
/* Layer register offsets */ /* Layer register offsets */
...@@ -121,6 +122,7 @@ ...@@ -121,6 +122,7 @@
#define GCR_LTDCEN BIT(0) /* LTDC ENable */ #define GCR_LTDCEN BIT(0) /* LTDC ENable */
#define GCR_DEN BIT(16) /* Dither ENable */ #define GCR_DEN BIT(16) /* Dither ENable */
#define GCR_CRCEN BIT(19) /* CRC ENable */
#define GCR_PCPOL BIT(28) /* Pixel Clock POLarity-Inverted */ #define GCR_PCPOL BIT(28) /* Pixel Clock POLarity-Inverted */
#define GCR_DEPOL BIT(29) /* Data Enable POLarity-High */ #define GCR_DEPOL BIT(29) /* Data Enable POLarity-High */
#define GCR_VSPOL BIT(30) /* Vertical Synchro POLarity-High */ #define GCR_VSPOL BIT(30) /* Vertical Synchro POLarity-High */
...@@ -227,6 +229,13 @@ ...@@ -227,6 +229,13 @@
#define NB_PF 8 /* Max nb of HW pixel format */ #define NB_PF 8 /* Max nb of HW pixel format */
/*
* Skip the first value and the second in case CRC was enabled during
* the thread irq. This is to be sure CRC value is relevant for the
* frame.
*/
#define CRC_SKIP_FRAMES 2
enum ltdc_pix_fmt { enum ltdc_pix_fmt {
PF_NONE, PF_NONE,
/* RGB formats */ /* RGB formats */
...@@ -624,7 +633,8 @@ static inline void ltdc_set_ycbcr_config(struct drm_plane *plane, u32 drm_pix_fm ...@@ -624,7 +633,8 @@ static inline void ltdc_set_ycbcr_config(struct drm_plane *plane, u32 drm_pix_fm
break; break;
default: default:
/* RGB or not a YCbCr supported format */ /* RGB or not a YCbCr supported format */
break; DRM_ERROR("Unsupported pixel format: %u\n", drm_pix_fmt);
return;
} }
/* Enable limited range */ /* Enable limited range */
...@@ -664,6 +674,26 @@ static inline void ltdc_set_ycbcr_coeffs(struct drm_plane *plane) ...@@ -664,6 +674,26 @@ static inline void ltdc_set_ycbcr_coeffs(struct drm_plane *plane)
ltdc_ycbcr2rgb_coeffs[enc][ran][1]); ltdc_ycbcr2rgb_coeffs[enc][ran][1]);
} }
static inline void ltdc_irq_crc_handle(struct ltdc_device *ldev,
struct drm_crtc *crtc)
{
u32 crc;
int ret;
if (ldev->crc_skip_count < CRC_SKIP_FRAMES) {
ldev->crc_skip_count++;
return;
}
/* Get the CRC of the frame */
ret = regmap_read(ldev->regmap, LTDC_CCRCR, &crc);
if (ret)
return;
/* Report to DRM the CRC (hw dependent feature) */
drm_crtc_add_crc_entry(crtc, true, drm_crtc_accurate_vblank_count(crtc), &crc);
}
static irqreturn_t ltdc_irq_thread(int irq, void *arg) static irqreturn_t ltdc_irq_thread(int irq, void *arg)
{ {
struct drm_device *ddev = arg; struct drm_device *ddev = arg;
...@@ -671,9 +701,14 @@ static irqreturn_t ltdc_irq_thread(int irq, void *arg) ...@@ -671,9 +701,14 @@ static irqreturn_t ltdc_irq_thread(int irq, void *arg)
struct drm_crtc *crtc = drm_crtc_from_index(ddev, 0); struct drm_crtc *crtc = drm_crtc_from_index(ddev, 0);
/* Line IRQ : trigger the vblank event */ /* Line IRQ : trigger the vblank event */
if (ldev->irq_status & ISR_LIF) if (ldev->irq_status & ISR_LIF) {
drm_crtc_handle_vblank(crtc); drm_crtc_handle_vblank(crtc);
/* Early return if CRC is not active */
if (ldev->crc_active)
ltdc_irq_crc_handle(ldev, crtc);
}
/* Save FIFO Underrun & Transfer Error status */ /* Save FIFO Underrun & Transfer Error status */
mutex_lock(&ldev->err_lock); mutex_lock(&ldev->err_lock);
if (ldev->irq_status & ISR_FUIF) if (ldev->irq_status & ISR_FUIF)
...@@ -1079,6 +1114,48 @@ static void ltdc_crtc_disable_vblank(struct drm_crtc *crtc) ...@@ -1079,6 +1114,48 @@ static void ltdc_crtc_disable_vblank(struct drm_crtc *crtc)
regmap_clear_bits(ldev->regmap, LTDC_IER, IER_LIE); regmap_clear_bits(ldev->regmap, LTDC_IER, IER_LIE);
} }
static int ltdc_crtc_set_crc_source(struct drm_crtc *crtc, const char *source)
{
struct ltdc_device *ldev = crtc_to_ltdc(crtc);
int ret;
DRM_DEBUG_DRIVER("\n");
if (!crtc)
return -ENODEV;
if (source && strcmp(source, "auto") == 0) {
ldev->crc_active = true;
ret = regmap_set_bits(ldev->regmap, LTDC_GCR, GCR_CRCEN);
} else if (!source) {
ldev->crc_active = false;
ret = regmap_clear_bits(ldev->regmap, LTDC_GCR, GCR_CRCEN);
} else {
ret = -EINVAL;
}
ldev->crc_skip_count = 0;
return ret;
}
static int ltdc_crtc_verify_crc_source(struct drm_crtc *crtc,
const char *source, size_t *values_cnt)
{
DRM_DEBUG_DRIVER("\n");
if (!crtc)
return -ENODEV;
if (source && strcmp(source, "auto") != 0) {
DRM_DEBUG_DRIVER("Unknown CRC source %s for %s\n",
source, crtc->name);
return -EINVAL;
}
*values_cnt = 1;
return 0;
}
static const struct drm_crtc_funcs ltdc_crtc_funcs = { static const struct drm_crtc_funcs ltdc_crtc_funcs = {
.destroy = drm_crtc_cleanup, .destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config, .set_config = drm_atomic_helper_set_config,
...@@ -1091,6 +1168,20 @@ static const struct drm_crtc_funcs ltdc_crtc_funcs = { ...@@ -1091,6 +1168,20 @@ static const struct drm_crtc_funcs ltdc_crtc_funcs = {
.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
}; };
static const struct drm_crtc_funcs ltdc_crtc_with_crc_support_funcs = {
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.reset = drm_atomic_helper_crtc_reset,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
.enable_vblank = ltdc_crtc_enable_vblank,
.disable_vblank = ltdc_crtc_disable_vblank,
.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
.set_crc_source = ltdc_crtc_set_crc_source,
.verify_crc_source = ltdc_crtc_verify_crc_source,
};
/* /*
* DRM_PLANE * DRM_PLANE
*/ */
...@@ -1478,8 +1569,13 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) ...@@ -1478,8 +1569,13 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc)
drm_plane_create_zpos_immutable_property(primary, 0); drm_plane_create_zpos_immutable_property(primary, 0);
ret = drm_crtc_init_with_planes(ddev, crtc, primary, NULL, /* Init CRTC according to its hardware features */
&ltdc_crtc_funcs, NULL); if (ldev->caps.crc)
ret = drm_crtc_init_with_planes(ddev, crtc, primary, NULL,
&ltdc_crtc_with_crc_support_funcs, NULL);
else
ret = drm_crtc_init_with_planes(ddev, crtc, primary, NULL,
&ltdc_crtc_funcs, NULL);
if (ret) { if (ret) {
DRM_ERROR("Can not initialize CRTC\n"); DRM_ERROR("Can not initialize CRTC\n");
goto cleanup; goto cleanup;
...@@ -1629,6 +1725,7 @@ static int ltdc_get_caps(struct drm_device *ddev) ...@@ -1629,6 +1725,7 @@ static int ltdc_get_caps(struct drm_device *ddev)
ldev->caps.ycbcr_input = false; ldev->caps.ycbcr_input = false;
ldev->caps.ycbcr_output = false; ldev->caps.ycbcr_output = false;
ldev->caps.plane_reg_shadow = false; ldev->caps.plane_reg_shadow = false;
ldev->caps.crc = false;
break; break;
case HWVER_20101: case HWVER_20101:
ldev->caps.layer_ofs = LAY_OFS_0; ldev->caps.layer_ofs = LAY_OFS_0;
...@@ -1643,6 +1740,7 @@ static int ltdc_get_caps(struct drm_device *ddev) ...@@ -1643,6 +1740,7 @@ static int ltdc_get_caps(struct drm_device *ddev)
ldev->caps.ycbcr_input = false; ldev->caps.ycbcr_input = false;
ldev->caps.ycbcr_output = false; ldev->caps.ycbcr_output = false;
ldev->caps.plane_reg_shadow = false; ldev->caps.plane_reg_shadow = false;
ldev->caps.crc = false;
break; break;
case HWVER_40100: case HWVER_40100:
ldev->caps.layer_ofs = LAY_OFS_1; ldev->caps.layer_ofs = LAY_OFS_1;
...@@ -1657,6 +1755,7 @@ static int ltdc_get_caps(struct drm_device *ddev) ...@@ -1657,6 +1755,7 @@ static int ltdc_get_caps(struct drm_device *ddev)
ldev->caps.ycbcr_input = true; ldev->caps.ycbcr_input = true;
ldev->caps.ycbcr_output = true; ldev->caps.ycbcr_output = true;
ldev->caps.plane_reg_shadow = true; ldev->caps.plane_reg_shadow = true;
ldev->caps.crc = true;
break; break;
default: default:
return -ENODEV; return -ENODEV;
......
...@@ -27,6 +27,7 @@ struct ltdc_caps { ...@@ -27,6 +27,7 @@ struct ltdc_caps {
bool ycbcr_input; /* ycbcr input converter supported */ bool ycbcr_input; /* ycbcr input converter supported */
bool ycbcr_output; /* ycbcr output converter supported */ bool ycbcr_output; /* ycbcr output converter supported */
bool plane_reg_shadow; /* plane shadow registers ability */ bool plane_reg_shadow; /* plane shadow registers ability */
bool crc; /* cyclic redundancy check supported */
}; };
#define LTDC_MAX_LAYER 4 #define LTDC_MAX_LAYER 4
...@@ -46,6 +47,8 @@ struct ltdc_device { ...@@ -46,6 +47,8 @@ struct ltdc_device {
u32 irq_status; u32 irq_status;
struct fps_info plane_fpsi[LTDC_MAX_LAYER]; struct fps_info plane_fpsi[LTDC_MAX_LAYER];
struct drm_atomic_state *suspend_state; struct drm_atomic_state *suspend_state;
int crc_skip_count;
bool crc_active;
}; };
int ltdc_load(struct drm_device *ddev); int ltdc_load(struct drm_device *ddev);
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
static void sun4i_backend_layer_reset(struct drm_plane *plane) static void sun4i_backend_layer_reset(struct drm_plane *plane)
{ {
struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
struct sun4i_layer_state *state; struct sun4i_layer_state *state;
if (plane->state) { if (plane->state) {
...@@ -31,10 +30,8 @@ static void sun4i_backend_layer_reset(struct drm_plane *plane) ...@@ -31,10 +30,8 @@ static void sun4i_backend_layer_reset(struct drm_plane *plane)
} }
state = kzalloc(sizeof(*state), GFP_KERNEL); state = kzalloc(sizeof(*state), GFP_KERNEL);
if (state) { if (state)
__drm_atomic_helper_plane_reset(plane, &state->state); __drm_atomic_helper_plane_reset(plane, &state->state);
plane->state->zpos = layer->id;
}
} }
static struct drm_plane_state * static struct drm_plane_state *
...@@ -192,7 +189,8 @@ static const uint64_t sun4i_layer_modifiers[] = { ...@@ -192,7 +189,8 @@ static const uint64_t sun4i_layer_modifiers[] = {
static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
struct sun4i_backend *backend, struct sun4i_backend *backend,
enum drm_plane_type type) enum drm_plane_type type,
unsigned int id)
{ {
const uint64_t *modifiers = sun4i_layer_modifiers; const uint64_t *modifiers = sun4i_layer_modifiers;
const uint32_t *formats = sun4i_layer_formats; const uint32_t *formats = sun4i_layer_formats;
...@@ -204,6 +202,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, ...@@ -204,6 +202,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
if (!layer) if (!layer)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
layer->id = id;
layer->backend = backend; layer->backend = backend;
if (IS_ERR_OR_NULL(backend->frontend)) { if (IS_ERR_OR_NULL(backend->frontend)) {
...@@ -226,8 +225,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, ...@@ -226,8 +225,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
&sun4i_backend_layer_helper_funcs); &sun4i_backend_layer_helper_funcs);
drm_plane_create_alpha_property(&layer->plane); drm_plane_create_alpha_property(&layer->plane);
drm_plane_create_zpos_property(&layer->plane, 0, 0, drm_plane_create_zpos_property(&layer->plane, layer->id,
SUN4I_BACKEND_NUM_LAYERS - 1); 0, SUN4I_BACKEND_NUM_LAYERS - 1);
return layer; return layer;
} }
...@@ -249,14 +248,13 @@ struct drm_plane **sun4i_layers_init(struct drm_device *drm, ...@@ -249,14 +248,13 @@ struct drm_plane **sun4i_layers_init(struct drm_device *drm,
enum drm_plane_type type = i ? DRM_PLANE_TYPE_OVERLAY : DRM_PLANE_TYPE_PRIMARY; enum drm_plane_type type = i ? DRM_PLANE_TYPE_OVERLAY : DRM_PLANE_TYPE_PRIMARY;
struct sun4i_layer *layer; struct sun4i_layer *layer;
layer = sun4i_layer_init_one(drm, backend, type); layer = sun4i_layer_init_one(drm, backend, type, i);
if (IS_ERR(layer)) { if (IS_ERR(layer)) {
dev_err(drm->dev, "Couldn't initialize %s plane\n", dev_err(drm->dev, "Couldn't initialize %s plane\n",
i ? "overlay" : "primary"); i ? "overlay" : "primary");
return ERR_CAST(layer); return ERR_CAST(layer);
} }
layer->id = i;
planes[i] = &layer->plane; planes[i] = &layer->plane;
} }
......
...@@ -549,6 +549,15 @@ static void drm_dp_link_get_adjustments(struct drm_dp_link *link, ...@@ -549,6 +549,15 @@ static void drm_dp_link_get_adjustments(struct drm_dp_link *link,
{ {
struct drm_dp_link_train_set *adjust = &link->train.adjust; struct drm_dp_link_train_set *adjust = &link->train.adjust;
unsigned int i; unsigned int i;
u8 post_cursor;
int err;
err = drm_dp_dpcd_read(link->aux, DP_ADJUST_REQUEST_POST_CURSOR2,
&post_cursor, sizeof(post_cursor));
if (err < 0) {
DRM_ERROR("failed to read post_cursor2: %d\n", err);
post_cursor = 0;
}
for (i = 0; i < link->lanes; i++) { for (i = 0; i < link->lanes; i++) {
adjust->voltage_swing[i] = adjust->voltage_swing[i] =
...@@ -560,7 +569,7 @@ static void drm_dp_link_get_adjustments(struct drm_dp_link *link, ...@@ -560,7 +569,7 @@ static void drm_dp_link_get_adjustments(struct drm_dp_link *link,
DP_TRAIN_PRE_EMPHASIS_SHIFT; DP_TRAIN_PRE_EMPHASIS_SHIFT;
adjust->post_cursor[i] = adjust->post_cursor[i] =
drm_dp_get_adjust_request_post_cursor(status, i); (post_cursor >> (i << 1)) & 0x3;
} }
} }
......
...@@ -51,6 +51,21 @@ config DRM_GM12U320 ...@@ -51,6 +51,21 @@ config DRM_GM12U320
This is a KMS driver for projectors which use the GM12U320 chipset This is a KMS driver for projectors which use the GM12U320 chipset
for video transfer over USB2/3, such as the Acer C120 mini projector. for video transfer over USB2/3, such as the Acer C120 mini projector.
config DRM_PANEL_MIPI_DBI
tristate "DRM support for MIPI DBI compatible panels"
depends on DRM && SPI
select DRM_KMS_HELPER
select DRM_GEM_CMA_HELPER
select DRM_MIPI_DBI
select BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
help
Say Y here if you want to enable support for MIPI DBI compatible
panels. The controller command setup can be provided using a
firmware file. For more information see
https://github.com/notro/panel-mipi-dbi/wiki.
To compile this driver as a module, choose M here.
config DRM_SIMPLEDRM config DRM_SIMPLEDRM
tristate "Simple framebuffer driver" tristate "Simple framebuffer driver"
depends on DRM && MMU depends on DRM && MMU
......
...@@ -4,6 +4,7 @@ obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o ...@@ -4,6 +4,7 @@ obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o
obj-$(CONFIG_DRM_BOCHS) += bochs.o obj-$(CONFIG_DRM_BOCHS) += bochs.o
obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o
obj-$(CONFIG_DRM_GM12U320) += gm12u320.o obj-$(CONFIG_DRM_GM12U320) += gm12u320.o
obj-$(CONFIG_DRM_PANEL_MIPI_DBI) += panel-mipi-dbi.o
obj-$(CONFIG_DRM_SIMPLEDRM) += simpledrm.o obj-$(CONFIG_DRM_SIMPLEDRM) += simpledrm.o
obj-$(CONFIG_TINYDRM_HX8357D) += hx8357d.o obj-$(CONFIG_TINYDRM_HX8357D) += hx8357d.o
obj-$(CONFIG_TINYDRM_ILI9163) += ili9163.o obj-$(CONFIG_TINYDRM_ILI9163) += ili9163.o
......
This diff is collapsed.
...@@ -508,26 +508,6 @@ static void repaper_get_temperature(struct repaper_epd *epd) ...@@ -508,26 +508,6 @@ static void repaper_get_temperature(struct repaper_epd *epd)
epd->factored_stage_time = epd->stage_time * factor10x / 10; epd->factored_stage_time = epd->stage_time * factor10x / 10;
} }
static void repaper_gray8_to_mono_reversed(u8 *buf, u32 width, u32 height)
{
u8 *gray8 = buf, *mono = buf;
int y, xb, i;
for (y = 0; y < height; y++)
for (xb = 0; xb < width / 8; xb++) {
u8 byte = 0x00;
for (i = 0; i < 8; i++) {
int x = xb * 8 + i;
byte >>= 1;
if (gray8[y * width + x] >> 7)
byte |= BIT(7);
}
*mono++ = byte;
}
}
static int repaper_fb_dirty(struct drm_framebuffer *fb) static int repaper_fb_dirty(struct drm_framebuffer *fb)
{ {
struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
...@@ -560,12 +540,10 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb) ...@@ -560,12 +540,10 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb)
if (ret) if (ret)
goto out_free; goto out_free;
drm_fb_xrgb8888_to_gray8(buf, 0, cma_obj->vaddr, fb, &clip); drm_fb_xrgb8888_to_mono_reversed(buf, 0, cma_obj->vaddr, fb, &clip);
drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
repaper_gray8_to_mono_reversed(buf, fb->width, fb->height);
if (epd->partial) { if (epd->partial) {
repaper_frame_data_repeat(epd, buf, epd->current_frame, repaper_frame_data_repeat(epd, buf, epd->current_frame,
REPAPER_NORMAL); REPAPER_NORMAL);
......
...@@ -810,6 +810,9 @@ static int simpledrm_device_init_modeset(struct simpledrm_device *sdev) ...@@ -810,6 +810,9 @@ static int simpledrm_device_init_modeset(struct simpledrm_device *sdev)
if (ret) if (ret)
return ret; return ret;
drm_connector_helper_add(connector, &simpledrm_connector_helper_funcs); drm_connector_helper_add(connector, &simpledrm_connector_helper_funcs);
drm_connector_set_panel_orientation_with_quirk(connector,
DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
mode->hdisplay, mode->vdisplay);
formats = simpledrm_device_formats(sdev, &nformats); formats = simpledrm_device_formats(sdev, &nformats);
......
...@@ -392,34 +392,24 @@ v3d_sched_init(struct v3d_dev *v3d) ...@@ -392,34 +392,24 @@ v3d_sched_init(struct v3d_dev *v3d)
hw_jobs_limit, job_hang_limit, hw_jobs_limit, job_hang_limit,
msecs_to_jiffies(hang_limit_ms), NULL, msecs_to_jiffies(hang_limit_ms), NULL,
NULL, "v3d_bin", v3d->drm.dev); NULL, "v3d_bin", v3d->drm.dev);
if (ret) { if (ret)
dev_err(v3d->drm.dev, "Failed to create bin scheduler: %d.", ret);
return ret; return ret;
}
ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched,
&v3d_render_sched_ops, &v3d_render_sched_ops,
hw_jobs_limit, job_hang_limit, hw_jobs_limit, job_hang_limit,
msecs_to_jiffies(hang_limit_ms), NULL, msecs_to_jiffies(hang_limit_ms), NULL,
NULL, "v3d_render", v3d->drm.dev); NULL, "v3d_render", v3d->drm.dev);
if (ret) { if (ret)
dev_err(v3d->drm.dev, "Failed to create render scheduler: %d.", goto fail;
ret);
v3d_sched_fini(v3d);
return ret;
}
ret = drm_sched_init(&v3d->queue[V3D_TFU].sched, ret = drm_sched_init(&v3d->queue[V3D_TFU].sched,
&v3d_tfu_sched_ops, &v3d_tfu_sched_ops,
hw_jobs_limit, job_hang_limit, hw_jobs_limit, job_hang_limit,
msecs_to_jiffies(hang_limit_ms), NULL, msecs_to_jiffies(hang_limit_ms), NULL,
NULL, "v3d_tfu", v3d->drm.dev); NULL, "v3d_tfu", v3d->drm.dev);
if (ret) { if (ret)
dev_err(v3d->drm.dev, "Failed to create TFU scheduler: %d.", goto fail;
ret);
v3d_sched_fini(v3d);
return ret;
}
if (v3d_has_csd(v3d)) { if (v3d_has_csd(v3d)) {
ret = drm_sched_init(&v3d->queue[V3D_CSD].sched, ret = drm_sched_init(&v3d->queue[V3D_CSD].sched,
...@@ -427,27 +417,23 @@ v3d_sched_init(struct v3d_dev *v3d) ...@@ -427,27 +417,23 @@ v3d_sched_init(struct v3d_dev *v3d)
hw_jobs_limit, job_hang_limit, hw_jobs_limit, job_hang_limit,
msecs_to_jiffies(hang_limit_ms), NULL, msecs_to_jiffies(hang_limit_ms), NULL,
NULL, "v3d_csd", v3d->drm.dev); NULL, "v3d_csd", v3d->drm.dev);
if (ret) { if (ret)
dev_err(v3d->drm.dev, "Failed to create CSD scheduler: %d.", goto fail;
ret);
v3d_sched_fini(v3d);
return ret;
}
ret = drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched, ret = drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched,
&v3d_cache_clean_sched_ops, &v3d_cache_clean_sched_ops,
hw_jobs_limit, job_hang_limit, hw_jobs_limit, job_hang_limit,
msecs_to_jiffies(hang_limit_ms), NULL, msecs_to_jiffies(hang_limit_ms), NULL,
NULL, "v3d_cache_clean", v3d->drm.dev); NULL, "v3d_cache_clean", v3d->drm.dev);
if (ret) { if (ret)
dev_err(v3d->drm.dev, "Failed to create CACHE_CLEAN scheduler: %d.", goto fail;
ret);
v3d_sched_fini(v3d);
return ret;
}
} }
return 0; return 0;
fail:
v3d_sched_fini(v3d);
return ret;
} }
void void
......
...@@ -16,15 +16,15 @@ ...@@ -16,15 +16,15 @@
* must be laid out exactly in the same format as the framebuffer. Yes I know * must be laid out exactly in the same format as the framebuffer. Yes I know
* their are cards with hardware that coverts images of various depths to the * their are cards with hardware that coverts images of various depths to the
* framebuffer depth. But not every card has this. All images must be rounded * framebuffer depth. But not every card has this. All images must be rounded
* up to the nearest byte. For example a bitmap 12 bits wide must be two * up to the nearest byte. For example a bitmap 12 bits wide must be two
* bytes width. * bytes width.
* *
* Tony: * Tony:
* Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds * Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds
* up the code significantly. * up the code significantly.
* *
* Code for depths not multiples of BITS_PER_LONG is still kludgy, which is * Code for depths not multiples of BITS_PER_LONG is still kludgy, which is
* still processed a bit at a time. * still processed a bit at a time.
* *
* Also need to add code to deal with cards endians that are different than * Also need to add code to deal with cards endians that are different than
* the native cpu endians. I also need to deal with MSB position in the word. * the native cpu endians. I also need to deal with MSB position in the word.
...@@ -72,8 +72,8 @@ static const u32 cfb_tab32[] = { ...@@ -72,8 +72,8 @@ static const u32 cfb_tab32[] = {
#define FB_WRITEL fb_writel #define FB_WRITEL fb_writel
#define FB_READL fb_readl #define FB_READL fb_readl
static inline void color_imageblit(const struct fb_image *image, static inline void color_imageblit(const struct fb_image *image,
struct fb_info *p, u8 __iomem *dst1, struct fb_info *p, u8 __iomem *dst1,
u32 start_index, u32 start_index,
u32 pitch_index) u32 pitch_index)
{ {
...@@ -92,7 +92,7 @@ static inline void color_imageblit(const struct fb_image *image, ...@@ -92,7 +92,7 @@ static inline void color_imageblit(const struct fb_image *image,
dst = (u32 __iomem *) dst1; dst = (u32 __iomem *) dst1;
shift = 0; shift = 0;
val = 0; val = 0;
if (start_index) { if (start_index) {
u32 start_mask = ~fb_shifted_pixels_mask_u32(p, u32 start_mask = ~fb_shifted_pixels_mask_u32(p,
start_index, bswapmask); start_index, bswapmask);
...@@ -109,8 +109,8 @@ static inline void color_imageblit(const struct fb_image *image, ...@@ -109,8 +109,8 @@ static inline void color_imageblit(const struct fb_image *image,
val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask); val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
if (shift >= null_bits) { if (shift >= null_bits) {
FB_WRITEL(val, dst++); FB_WRITEL(val, dst++);
val = (shift == null_bits) ? 0 : val = (shift == null_bits) ? 0 :
FB_SHIFT_LOW(p, color, 32 - shift); FB_SHIFT_LOW(p, color, 32 - shift);
} }
shift += bpp; shift += bpp;
...@@ -134,9 +134,9 @@ static inline void color_imageblit(const struct fb_image *image, ...@@ -134,9 +134,9 @@ static inline void color_imageblit(const struct fb_image *image,
} }
} }
static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p, static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p,
u8 __iomem *dst1, u32 fgcolor, u8 __iomem *dst1, u32 fgcolor,
u32 bgcolor, u32 bgcolor,
u32 start_index, u32 start_index,
u32 pitch_index) u32 pitch_index)
{ {
...@@ -172,7 +172,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * ...@@ -172,7 +172,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
l--; l--;
color = (*s & (1 << l)) ? fgcolor : bgcolor; color = (*s & (1 << l)) ? fgcolor : bgcolor;
val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask); val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
/* Did the bitshift spill bits to the next long? */ /* Did the bitshift spill bits to the next long? */
if (shift >= null_bits) { if (shift >= null_bits) {
FB_WRITEL(val, dst++); FB_WRITEL(val, dst++);
...@@ -191,16 +191,16 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * ...@@ -191,16 +191,16 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
} }
dst1 += pitch; dst1 += pitch;
src += spitch; src += spitch;
if (pitch_index) { if (pitch_index) {
dst2 += pitch; dst2 += pitch;
dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1)); dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
start_index += pitch_index; start_index += pitch_index;
start_index &= 32 - 1; start_index &= 32 - 1;
} }
} }
} }
...@@ -212,29 +212,35 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * ...@@ -212,29 +212,35 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
* fix->line_legth is divisible by 4; * fix->line_legth is divisible by 4;
* beginning and end of a scanline is dword aligned * beginning and end of a scanline is dword aligned
*/ */
static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p, static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p,
u8 __iomem *dst1, u32 fgcolor, u8 __iomem *dst1, u32 fgcolor,
u32 bgcolor) u32 bgcolor)
{ {
u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
u32 ppw = 32/bpp, spitch = (image->width + 7)/8; u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
u32 bit_mask, end_mask, eorx, shift; u32 bit_mask, eorx;
const char *s = image->data, *src; const char *s = image->data, *src;
u32 __iomem *dst; u32 __iomem *dst;
const u32 *tab = NULL; const u32 *tab = NULL;
size_t tablen;
u32 colortab[16];
int i, j, k; int i, j, k;
switch (bpp) { switch (bpp) {
case 8: case 8:
tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le; tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
tablen = 16;
break; break;
case 16: case 16:
tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
tablen = 4;
break; break;
case 32: case 32:
default:
tab = cfb_tab32; tab = cfb_tab32;
tablen = 2;
break; break;
default:
return;
} }
for (i = ppw-1; i--; ) { for (i = ppw-1; i--; ) {
...@@ -243,25 +249,52 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * ...@@ -243,25 +249,52 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info *
fgx |= fgcolor; fgx |= fgcolor;
bgx |= bgcolor; bgx |= bgcolor;
} }
bit_mask = (1 << ppw) - 1; bit_mask = (1 << ppw) - 1;
eorx = fgx ^ bgx; eorx = fgx ^ bgx;
k = image->width/ppw; k = image->width/ppw;
for (i = 0; i < tablen; ++i)
colortab[i] = (tab[i] & eorx) ^ bgx;
for (i = image->height; i--; ) { for (i = image->height; i--; ) {
dst = (u32 __iomem *) dst1, shift = 8; src = s; dst = (u32 __iomem *)dst1;
src = s;
for (j = k; j--; ) {
shift -= ppw; switch (ppw) {
end_mask = tab[(*src >> shift) & bit_mask]; case 4: /* 8 bpp */
FB_WRITEL((end_mask & eorx)^bgx, dst++); for (j = k; j; j -= 2, ++src) {
if (!shift) { shift = 8; src++; } FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++);
FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++);
}
break;
case 2: /* 16 bpp */
for (j = k; j; j -= 4, ++src) {
FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++);
FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++);
FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++);
FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++);
}
break;
case 1: /* 32 bpp */
for (j = k; j; j -= 8, ++src) {
FB_WRITEL(colortab[(*src >> 7) & bit_mask], dst++);
FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++);
FB_WRITEL(colortab[(*src >> 5) & bit_mask], dst++);
FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++);
FB_WRITEL(colortab[(*src >> 3) & bit_mask], dst++);
FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++);
FB_WRITEL(colortab[(*src >> 1) & bit_mask], dst++);
FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++);
}
break;
} }
dst1 += p->fix.line_length; dst1 += p->fix.line_length;
s += spitch; s += spitch;
} }
} }
void cfb_imageblit(struct fb_info *p, const struct fb_image *image) void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
{ {
u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
...@@ -292,13 +325,13 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image) ...@@ -292,13 +325,13 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
} else { } else {
fgcolor = image->fg_color; fgcolor = image->fg_color;
bgcolor = image->bg_color; bgcolor = image->bg_color;
} }
if (32 % bpp == 0 && !start_index && !pitch_index && if (32 % bpp == 0 && !start_index && !pitch_index &&
((width & (32/bpp-1)) == 0) && ((width & (32/bpp-1)) == 0) &&
bpp >= 8 && bpp <= 32) bpp >= 8 && bpp <= 32)
fast_imageblit(image, p, dst1, fgcolor, bgcolor); fast_imageblit(image, p, dst1, fgcolor, bgcolor);
else else
slow_imageblit(image, p, dst1, fgcolor, bgcolor, slow_imageblit(image, p, dst1, fgcolor, bgcolor,
start_index, pitch_index); start_index, pitch_index);
} else } else
......
...@@ -50,19 +50,9 @@ bitfill_aligned(struct fb_info *p, unsigned long *dst, int dst_idx, ...@@ -50,19 +50,9 @@ bitfill_aligned(struct fb_info *p, unsigned long *dst, int dst_idx,
/* Main chunk */ /* Main chunk */
n /= bits; n /= bits;
while (n >= 8) { memset_l(dst, pat, n);
*dst++ = pat; dst += n;
*dst++ = pat;
*dst++ = pat;
*dst++ = pat;
*dst++ = pat;
*dst++ = pat;
*dst++ = pat;
*dst++ = pat;
n -= 8;
}
while (n--)
*dst++ = pat;
/* Trailing bits */ /* Trailing bits */
if (last) if (last)
*dst = comp(pat, *dst, last); *dst = comp(pat, *dst, last);
......
...@@ -188,23 +188,29 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p, ...@@ -188,23 +188,29 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
{ {
u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
u32 ppw = 32/bpp, spitch = (image->width + 7)/8; u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
u32 bit_mask, end_mask, eorx, shift; u32 bit_mask, eorx;
const char *s = image->data, *src; const char *s = image->data, *src;
u32 *dst; u32 *dst;
const u32 *tab = NULL; const u32 *tab;
size_t tablen;
u32 colortab[16];
int i, j, k; int i, j, k;
switch (bpp) { switch (bpp) {
case 8: case 8:
tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le; tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
tablen = 16;
break; break;
case 16: case 16:
tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
tablen = 4;
break; break;
case 32: case 32:
default:
tab = cfb_tab32; tab = cfb_tab32;
tablen = 2;
break; break;
default:
return;
} }
for (i = ppw-1; i--; ) { for (i = ppw-1; i--; ) {
...@@ -218,19 +224,40 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p, ...@@ -218,19 +224,40 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
eorx = fgx ^ bgx; eorx = fgx ^ bgx;
k = image->width/ppw; k = image->width/ppw;
for (i = 0; i < tablen; ++i)
colortab[i] = (tab[i] & eorx) ^ bgx;
for (i = image->height; i--; ) { for (i = image->height; i--; ) {
dst = dst1; dst = dst1;
shift = 8;
src = s; src = s;
for (j = k; j--; ) { switch (ppw) {
shift -= ppw; case 4: /* 8 bpp */
end_mask = tab[(*src >> shift) & bit_mask]; for (j = k; j; j -= 2, ++src) {
*dst++ = (end_mask & eorx) ^ bgx; *dst++ = colortab[(*src >> 4) & bit_mask];
if (!shift) { *dst++ = colortab[(*src >> 0) & bit_mask];
shift = 8; }
src++; break;
case 2: /* 16 bpp */
for (j = k; j; j -= 4, ++src) {
*dst++ = colortab[(*src >> 6) & bit_mask];
*dst++ = colortab[(*src >> 4) & bit_mask];
*dst++ = colortab[(*src >> 2) & bit_mask];
*dst++ = colortab[(*src >> 0) & bit_mask];
}
break;
case 1: /* 32 bpp */
for (j = k; j; j -= 8, ++src) {
*dst++ = colortab[(*src >> 7) & bit_mask];
*dst++ = colortab[(*src >> 6) & bit_mask];
*dst++ = colortab[(*src >> 5) & bit_mask];
*dst++ = colortab[(*src >> 4) & bit_mask];
*dst++ = colortab[(*src >> 3) & bit_mask];
*dst++ = colortab[(*src >> 2) & bit_mask];
*dst++ = colortab[(*src >> 1) & bit_mask];
*dst++ = colortab[(*src >> 0) & bit_mask];
} }
break;
} }
dst1 += p->fix.line_length; dst1 += p->fix.line_length;
s += spitch; s += spitch;
......
...@@ -456,7 +456,7 @@ struct drm_panel; ...@@ -456,7 +456,7 @@ struct drm_panel;
#define DP_FEC_CAPABILITY_1 0x091 /* 2.0 */ #define DP_FEC_CAPABILITY_1 0x091 /* 2.0 */
/* DP-HDMI2.1 PCON DSC ENCODER SUPPORT */ /* DP-HDMI2.1 PCON DSC ENCODER SUPPORT */
#define DP_PCON_DSC_ENCODER_CAP_SIZE 0xC /* 0x9E - 0x92 */ #define DP_PCON_DSC_ENCODER_CAP_SIZE 0xD /* 0x92 through 0x9E */
#define DP_PCON_DSC_ENCODER 0x092 #define DP_PCON_DSC_ENCODER 0x092
# define DP_PCON_DSC_ENCODER_SUPPORTED (1 << 0) # define DP_PCON_DSC_ENCODER_SUPPORTED (1 << 0)
# define DP_PCON_DSC_PPS_ENC_OVERRIDE (1 << 1) # define DP_PCON_DSC_PPS_ENC_OVERRIDE (1 << 1)
...@@ -1530,8 +1530,6 @@ u8 drm_dp_get_adjust_request_pre_emphasis(const u8 link_status[DP_LINK_STATUS_SI ...@@ -1530,8 +1530,6 @@ u8 drm_dp_get_adjust_request_pre_emphasis(const u8 link_status[DP_LINK_STATUS_SI
int lane); int lane);
u8 drm_dp_get_adjust_tx_ffe_preset(const u8 link_status[DP_LINK_STATUS_SIZE], u8 drm_dp_get_adjust_tx_ffe_preset(const u8 link_status[DP_LINK_STATUS_SIZE],
int lane); int lane);
u8 drm_dp_get_adjust_request_post_cursor(const u8 link_status[DP_LINK_STATUS_SIZE],
unsigned int lane);
#define DP_BRANCH_OUI_HEADER_SIZE 0xc #define DP_BRANCH_OUI_HEADER_SIZE 0xc
#define DP_RECEIVER_CAP_SIZE 0xf #define DP_RECEIVER_CAP_SIZE 0xf
......
...@@ -130,6 +130,14 @@ struct mipi_dbi_dev { ...@@ -130,6 +130,14 @@ struct mipi_dbi_dev {
* @dbi: MIPI DBI interface * @dbi: MIPI DBI interface
*/ */
struct mipi_dbi dbi; struct mipi_dbi dbi;
/**
* @driver_private: Driver private data.
* Necessary for drivers with private data since devm_drm_dev_alloc()
* can't allocate structures that embed a structure which then again
* embeds drm_device.
*/
void *driver_private;
}; };
static inline struct mipi_dbi_dev *drm_to_mipi_dbi_dev(struct drm_device *drm) static inline struct mipi_dbi_dev *drm_to_mipi_dbi_dev(struct drm_device *drm)
......
...@@ -98,6 +98,10 @@ struct drm_object_properties { ...@@ -98,6 +98,10 @@ struct drm_object_properties {
* Hence atomic drivers should not use drm_object_property_set_value() * Hence atomic drivers should not use drm_object_property_set_value()
* and drm_object_property_get_value() on mutable objects, i.e. those * and drm_object_property_get_value() on mutable objects, i.e. those
* without the DRM_MODE_PROP_IMMUTABLE flag set. * without the DRM_MODE_PROP_IMMUTABLE flag set.
*
* For atomic drivers the default value of properties is stored in this
* array, so drm_object_property_get_default_value can be used to
* retrieve it.
*/ */
uint64_t values[DRM_OBJECT_MAX_PROPERTY]; uint64_t values[DRM_OBJECT_MAX_PROPERTY];
}; };
...@@ -126,6 +130,9 @@ int drm_object_property_set_value(struct drm_mode_object *obj, ...@@ -126,6 +130,9 @@ int drm_object_property_set_value(struct drm_mode_object *obj,
int drm_object_property_get_value(struct drm_mode_object *obj, int drm_object_property_get_value(struct drm_mode_object *obj,
struct drm_property *property, struct drm_property *property,
uint64_t *value); uint64_t *value);
int drm_object_property_get_default_value(struct drm_mode_object *obj,
struct drm_property *property,
uint64_t *val);
void drm_object_attach_property(struct drm_mode_object *obj, void drm_object_attach_property(struct drm_mode_object *obj,
struct drm_property *property, struct drm_property *property,
......
...@@ -466,6 +466,8 @@ void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags); ...@@ -466,6 +466,8 @@ void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags);
int of_get_drm_display_mode(struct device_node *np, int of_get_drm_display_mode(struct device_node *np,
struct drm_display_mode *dmode, u32 *bus_flags, struct drm_display_mode *dmode, u32 *bus_flags,
int index); int index);
int of_get_drm_panel_display_mode(struct device_node *np,
struct drm_display_mode *dmode, u32 *bus_flags);
#else #else
static inline int of_get_drm_display_mode(struct device_node *np, static inline int of_get_drm_display_mode(struct device_node *np,
struct drm_display_mode *dmode, struct drm_display_mode *dmode,
...@@ -473,6 +475,12 @@ static inline int of_get_drm_display_mode(struct device_node *np, ...@@ -473,6 +475,12 @@ static inline int of_get_drm_display_mode(struct device_node *np,
{ {
return -EINVAL; return -EINVAL;
} }
static inline int of_get_drm_panel_display_mode(struct device_node *np,
struct drm_display_mode *dmode, u32 *bus_flags)
{
return -EINVAL;
}
#endif #endif
void drm_mode_set_name(struct drm_display_mode *mode); void drm_mode_set_name(struct drm_display_mode *mode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment