UAPI Changes:
 
 Cross-subsystem Changes:
 
 Core Changes:
   - fbdev: Fix double-free, Remove unused scrolling acceleration
   - locking: improve logging for contented locks without backoff
   - dma-buf: Add dma_resv_for_each_fence iterator, and conversion of
     users
 
 Driver Changes:
   - nouveau: Various code style improvements
   - bridge: HPD improvements for lt9611uxc, eDP aux-bus support for
     ps8640, lvds-codec data-mapping selection support
   - panels: Vivax TPC-9150, Innolux G070Y2-T02, LOGIC Technologies
     LTTD800480070-L2RT, Sharp LS060T1SX01,
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCYWgczwAKCRDj7w1vZxhR
 xTwlAP9uzjFJqG22inn1fchteZMTvJG0JxLjdO9l6ORUMzsj/AD/SNC1MYAuUv3Y
 /McjFrd1C2yVvKfdmI+21SsY2q95sAE=
 =AwQ7
 -----END PGP SIGNATURE-----

Merge tag 'drm-misc-next-2021-10-14' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

drm-misc-next for 5.16:

UAPI Changes:

Cross-subsystem Changes:

Core Changes:
  - fbdev: Fix double-free, Remove unused scrolling acceleration
  - locking: improve logging for contented locks without backoff
  - dma-buf: Add dma_resv_for_each_fence iterator, and conversion of
    users

Driver Changes:
  - nouveau: Various code style improvements
  - bridge: HPD improvements for lt9611uxc, eDP aux-bus support for
    ps8640, lvds-codec data-mapping selection support
  - panels: Vivax TPC-9150, Innolux G070Y2-T02, LOGIC Technologies
    LTTD800480070-L2RT, Sharp LS060T1SX01,

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20211014120452.2wicnt6hobu3kbwb@gilmour
This commit is contained in:
Dave Airlie 2021-11-05 13:50:09 +10:00
Родитель d9bd054177 b3ec8cdf45
Коммит 5275a99e35
52 изменённых файлов: 939 добавлений и 860 удалений

Просмотреть файл

@ -49,11 +49,26 @@ properties:
properties: properties:
port@0: port@0:
$ref: /schemas/graph.yaml#/properties/port $ref: /schemas/graph.yaml#/$defs/port-base
description: | description: |
For LVDS encoders, port 0 is the parallel input For LVDS encoders, port 0 is the parallel input
For LVDS decoders, port 0 is the LVDS input For LVDS decoders, port 0 is the LVDS input
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-mapping:
enum:
- jeida-18
- jeida-24
- vesa-24
description: |
The color signals mapping order. See details in
Documentation/devicetree/bindings/display/panel/lvds.yaml
port@1: port@1:
$ref: /schemas/graph.yaml#/properties/port $ref: /schemas/graph.yaml#/properties/port
description: | description: |
@ -71,6 +86,22 @@ properties:
power-supply: true power-supply: true
if:
not:
properties:
compatible:
contains:
const: lvds-decoder
then:
properties:
ports:
properties:
port@0:
properties:
endpoint:
properties:
data-mapping: false
required: required:
- compatible - compatible
- ports - ports

Просмотреть файл

@ -40,6 +40,9 @@ properties:
vdd33-supply: vdd33-supply:
description: Regulator for 3.3V digital core power. description: Regulator for 3.3V digital core power.
aux-bus:
$ref: /schemas/display/dp-aux-bus.yaml#
ports: ports:
$ref: /schemas/graph.yaml#/properties/ports $ref: /schemas/graph.yaml#/properties/ports
@ -98,7 +101,21 @@ examples:
reg = <1>; reg = <1>;
ps8640_out: endpoint { ps8640_out: endpoint {
remote-endpoint = <&panel_in>; remote-endpoint = <&panel_in>;
}; };
};
};
aux-bus {
panel {
compatible = "boe,nv133fhm-n62";
power-supply = <&pp3300_dx_edp>;
backlight = <&backlight>;
port {
panel_in: endpoint {
remote-endpoint = <&ps8640_out>;
};
};
}; };
}; };
}; };

Просмотреть файл

@ -166,6 +166,8 @@ properties:
- innolux,at070tn92 - innolux,at070tn92
# Innolux G070Y2-L01 7" WVGA (800x480) TFT LCD panel # Innolux G070Y2-L01 7" WVGA (800x480) TFT LCD panel
- innolux,g070y2-l01 - innolux,g070y2-l01
# Innolux G070Y2-T02 7" WVGA (800x480) TFT LCD TTL panel
- innolux,g070y2-t02
# Innolux Corporation 10.1" G101ICE-L01 WXGA (1280x800) LVDS panel # Innolux Corporation 10.1" G101ICE-L01 WXGA (1280x800) LVDS panel
- innolux,g101ice-l01 - innolux,g101ice-l01
# Innolux Corporation 12.1" WXGA (1280x800) TFT LCD panel # Innolux Corporation 12.1" WXGA (1280x800) TFT LCD panel
@ -309,6 +311,8 @@ properties:
- urt,umsh-8596md-11t - urt,umsh-8596md-11t
- urt,umsh-8596md-19t - urt,umsh-8596md-19t
- urt,umsh-8596md-20t - urt,umsh-8596md-20t
# Vivax TPC-9150 tablet 9.0" WSVGA TFT LCD panel
- vivax,tpc9150-panel
# VXT 800x480 color TFT LCD panel # VXT 800x480 color TFT LCD panel
- vxt,vl050-8048nt-c01 - vxt,vl050-8048nt-c01
# Winstar Display Corporation 3.5" QVGA (320x240) TFT LCD panel # Winstar Display Corporation 3.5" QVGA (320x240) TFT LCD panel
@ -317,6 +321,7 @@ properties:
- yes-optoelectronics,ytc700tlag-05-201c - yes-optoelectronics,ytc700tlag-05-201c
backlight: true backlight: true
ddc-i2c-bus: true
enable-gpios: true enable-gpios: true
port: true port: true
power-supply: true power-supply: true

Просмотреть файл

@ -0,0 +1,56 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/panel/sharp,ls060t1sx01.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sharp Microelectronics 6.0" FullHD TFT LCD panel
maintainers:
- Dmitry Baryskov <dmitry.baryshkov@linaro.org>
allOf:
- $ref: panel-common.yaml#
properties:
compatible:
const: sharp,ls060t1sx01
reg: true
backlight: true
reset-gpios: true
port: true
avdd-supply:
description: handle of the regulator that provides the positive supply voltage
avee-supply:
description: handle of the regulator that provides the negative supply voltage
vddi-supply:
description: handle of the regulator that provides the I/O supply voltage
vddh-supply:
description: handle of the regulator that provides the analog supply voltage
required:
- compatible
- reg
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
dsi {
#address-cells = <1>;
#size-cells = <0>;
panel@0 {
compatible = "sharp,ls060t1sx01";
reg = <0>;
avdd-supply = <&pm8941_l22>;
backlight = <&backlight>;
reset-gpios = <&pm8916_gpios 25 GPIO_ACTIVE_LOW>;
};
};
...

Просмотреть файл

@ -1264,6 +1264,8 @@ patternProperties:
description: Vitesse Semiconductor Corporation description: Vitesse Semiconductor Corporation
"^vivante,.*": "^vivante,.*":
description: Vivante Corporation description: Vivante Corporation
"^vivax,.*":
description: Vivax brand by M SAN Grupa d.o.o.
"^vocore,.*": "^vocore,.*":
description: VoCore Studio description: VoCore Studio
"^voipac,.*": "^voipac,.*":

Просмотреть файл

@ -314,16 +314,19 @@ Level: Advanced
Garbage collect fbdev scrolling acceleration Garbage collect fbdev scrolling acceleration
-------------------------------------------- --------------------------------------------
Scroll acceleration is disabled in fbcon by hard-wiring p->scrollmode = Scroll acceleration has been disabled in fbcon. Now it works as the old
SCROLL_REDRAW. There's a ton of code this will allow us to remove: SCROLL_REDRAW mode. A ton of code was removed in fbcon.c and the hook bmove was
removed from fbcon_ops.
Remaining tasks:
- lots of code in fbcon.c - a bunch of the hooks in fbcon_ops could be removed or simplified by calling
- a bunch of the hooks in fbcon_ops, maybe the remaining hooks could be called
directly instead of the function table (with a switch on p->rotate) directly instead of the function table (with a switch on p->rotate)
- fb_copyarea is unused after this, and can be deleted from all drivers - fb_copyarea is unused after this, and can be deleted from all drivers
- after that, fb_copyarea can be deleted from fb_ops in include/linux/fb.h as
well as cfb_copyarea
Note that not all acceleration code can be deleted, since clearing and cursor Note that not all acceleration code can be deleted, since clearing and cursor
support is still accelerated, which might be good candidates for further support is still accelerated, which might be good candidates for further
deletion projects. deletion projects.

Просмотреть файл

@ -209,19 +209,14 @@ static void dma_buf_poll_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
dma_fence_put(fence); dma_fence_put(fence);
} }
static bool dma_buf_poll_shared(struct dma_resv *resv, static bool dma_buf_poll_add_cb(struct dma_resv *resv, bool write,
struct dma_buf_poll_cb_t *dcb) struct dma_buf_poll_cb_t *dcb)
{ {
struct dma_resv_list *fobj = dma_resv_shared_list(resv); struct dma_resv_iter cursor;
struct dma_fence *fence; struct dma_fence *fence;
int i, r; int r;
if (!fobj) dma_resv_for_each_fence(&cursor, resv, write, fence) {
return false;
for (i = 0; i < fobj->shared_count; ++i) {
fence = rcu_dereference_protected(fobj->shared[i],
dma_resv_held(resv));
dma_fence_get(fence); dma_fence_get(fence);
r = dma_fence_add_callback(fence, &dcb->cb, dma_buf_poll_cb); r = dma_fence_add_callback(fence, &dcb->cb, dma_buf_poll_cb);
if (!r) if (!r)
@ -232,24 +227,6 @@ static bool dma_buf_poll_shared(struct dma_resv *resv,
return false; return false;
} }
static bool dma_buf_poll_excl(struct dma_resv *resv,
struct dma_buf_poll_cb_t *dcb)
{
struct dma_fence *fence = dma_resv_excl_fence(resv);
int r;
if (!fence)
return false;
dma_fence_get(fence);
r = dma_fence_add_callback(fence, &dcb->cb, dma_buf_poll_cb);
if (!r)
return true;
dma_fence_put(fence);
return false;
}
static __poll_t dma_buf_poll(struct file *file, poll_table *poll) static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
{ {
struct dma_buf *dmabuf; struct dma_buf *dmabuf;
@ -282,8 +259,7 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
spin_unlock_irq(&dmabuf->poll.lock); spin_unlock_irq(&dmabuf->poll.lock);
if (events & EPOLLOUT) { if (events & EPOLLOUT) {
if (!dma_buf_poll_shared(resv, dcb) && if (!dma_buf_poll_add_cb(resv, true, dcb))
!dma_buf_poll_excl(resv, dcb))
/* No callback queued, wake up any other waiters */ /* No callback queued, wake up any other waiters */
dma_buf_poll_cb(NULL, &dcb->cb); dma_buf_poll_cb(NULL, &dcb->cb);
else else
@ -303,7 +279,7 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
spin_unlock_irq(&dmabuf->poll.lock); spin_unlock_irq(&dmabuf->poll.lock);
if (events & EPOLLIN) { if (events & EPOLLIN) {
if (!dma_buf_poll_excl(resv, dcb)) if (!dma_buf_poll_add_cb(resv, false, dcb))
/* No callback queued, wake up any other waiters */ /* No callback queued, wake up any other waiters */
dma_buf_poll_cb(NULL, &dcb->cb); dma_buf_poll_cb(NULL, &dcb->cb);
else else
@ -1356,10 +1332,9 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
{ {
struct dma_buf *buf_obj; struct dma_buf *buf_obj;
struct dma_buf_attachment *attach_obj; struct dma_buf_attachment *attach_obj;
struct dma_resv *robj; struct dma_resv_iter cursor;
struct dma_resv_list *fobj;
struct dma_fence *fence; struct dma_fence *fence;
int count = 0, attach_count, shared_count, i; int count = 0, attach_count;
size_t size = 0; size_t size = 0;
int ret; int ret;
@ -1386,21 +1361,10 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
file_inode(buf_obj->file)->i_ino, file_inode(buf_obj->file)->i_ino,
buf_obj->name ?: ""); buf_obj->name ?: "");
robj = buf_obj->resv; dma_resv_for_each_fence(&cursor, buf_obj->resv, true, fence) {
fence = dma_resv_excl_fence(robj); seq_printf(s, "\t%s fence: %s %s %ssignalled\n",
if (fence) dma_resv_iter_is_exclusive(&cursor) ?
seq_printf(s, "\tExclusive fence: %s %s %ssignalled\n", "Exclusive" : "Shared",
fence->ops->get_driver_name(fence),
fence->ops->get_timeline_name(fence),
dma_fence_is_signaled(fence) ? "" : "un");
fobj = rcu_dereference_protected(robj->fence,
dma_resv_held(robj));
shared_count = fobj ? fobj->shared_count : 0;
for (i = 0; i < shared_count; i++) {
fence = rcu_dereference_protected(fobj->shared[i],
dma_resv_held(robj));
seq_printf(s, "\tShared fence: %s %s %ssignalled\n",
fence->ops->get_driver_name(fence), fence->ops->get_driver_name(fence),
fence->ops->get_timeline_name(fence), fence->ops->get_timeline_name(fence),
dma_fence_is_signaled(fence) ? "" : "un"); dma_fence_is_signaled(fence) ? "" : "un");

Просмотреть файл

@ -333,10 +333,14 @@ static void dma_resv_iter_restart_unlocked(struct dma_resv_iter *cursor)
{ {
cursor->seq = read_seqcount_begin(&cursor->obj->seq); cursor->seq = read_seqcount_begin(&cursor->obj->seq);
cursor->index = -1; cursor->index = -1;
if (cursor->all_fences) cursor->shared_count = 0;
if (cursor->all_fences) {
cursor->fences = dma_resv_shared_list(cursor->obj); cursor->fences = dma_resv_shared_list(cursor->obj);
else if (cursor->fences)
cursor->shared_count = cursor->fences->shared_count;
} else {
cursor->fences = NULL; cursor->fences = NULL;
}
cursor->is_restarted = true; cursor->is_restarted = true;
} }
@ -363,7 +367,7 @@ static void dma_resv_iter_walk_unlocked(struct dma_resv_iter *cursor)
continue; continue;
} else if (!cursor->fences || } else if (!cursor->fences ||
cursor->index >= cursor->fences->shared_count) { cursor->index >= cursor->shared_count) {
cursor->fence = NULL; cursor->fence = NULL;
break; break;
@ -423,6 +427,57 @@ struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor)
} }
EXPORT_SYMBOL(dma_resv_iter_next_unlocked); EXPORT_SYMBOL(dma_resv_iter_next_unlocked);
/**
* dma_resv_iter_first - first fence from a locked dma_resv object
* @cursor: cursor to record the current position
*
* Return the first fence in the dma_resv object while holding the
* &dma_resv.lock.
*/
struct dma_fence *dma_resv_iter_first(struct dma_resv_iter *cursor)
{
struct dma_fence *fence;
dma_resv_assert_held(cursor->obj);
cursor->index = 0;
if (cursor->all_fences)
cursor->fences = dma_resv_shared_list(cursor->obj);
else
cursor->fences = NULL;
fence = dma_resv_excl_fence(cursor->obj);
if (!fence)
fence = dma_resv_iter_next(cursor);
cursor->is_restarted = true;
return fence;
}
EXPORT_SYMBOL_GPL(dma_resv_iter_first);
/**
* dma_resv_iter_next - next fence from a locked dma_resv object
* @cursor: cursor to record the current position
*
* Return the next fences from the dma_resv object while holding the
* &dma_resv.lock.
*/
struct dma_fence *dma_resv_iter_next(struct dma_resv_iter *cursor)
{
unsigned int idx;
dma_resv_assert_held(cursor->obj);
cursor->is_restarted = false;
if (!cursor->fences || cursor->index >= cursor->fences->shared_count)
return NULL;
idx = cursor->index++;
return rcu_dereference_protected(cursor->fences->shared[idx],
dma_resv_held(cursor->obj));
}
EXPORT_SYMBOL_GPL(dma_resv_iter_next);
/** /**
* dma_resv_copy_fences - Copy all fences from src to dst. * dma_resv_copy_fences - Copy all fences from src to dst.
* @dst: the destination reservation object * @dst: the destination reservation object
@ -448,10 +503,8 @@ int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src)
dma_resv_list_free(list); dma_resv_list_free(list);
dma_fence_put(excl); dma_fence_put(excl);
if (cursor.fences) { if (cursor.shared_count) {
unsigned int cnt = cursor.fences->shared_count; list = dma_resv_list_alloc(cursor.shared_count);
list = dma_resv_list_alloc(cnt);
if (!list) { if (!list) {
dma_resv_iter_end(&cursor); dma_resv_iter_end(&cursor);
return -ENOMEM; return -ENOMEM;
@ -522,7 +575,7 @@ int dma_resv_get_fences(struct dma_resv *obj, struct dma_fence **fence_excl,
if (fence_excl) if (fence_excl)
dma_fence_put(*fence_excl); dma_fence_put(*fence_excl);
count = cursor.fences ? cursor.fences->shared_count : 0; count = cursor.shared_count;
count += fence_excl ? 0 : 1; count += fence_excl ? 0 : 1;
/* Eventually re-allocate the array */ /* Eventually re-allocate the array */

Просмотреть файл

@ -100,6 +100,21 @@ config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
This has the potential to use a lot of memory and print some very This has the potential to use a lot of memory and print some very
large kernel messages. If in doubt, say "N". large kernel messages. If in doubt, say "N".
config DRM_DEBUG_MODESET_LOCK
bool "Enable backtrace history for lock contention"
depends on STACKTRACE_SUPPORT
depends on DEBUG_KERNEL
depends on EXPERT
select STACKDEPOT
default y if DEBUG_WW_MUTEX_SLOWPATH
help
Enable debug tracing of failures to gracefully handle drm modeset lock
contention. A history of each drm modeset lock path hitting -EDEADLK
will be saved until gracefully handled, and the backtrace will be
printed when attempting to lock a contended lock.
If in doubt, say "N".
config DRM_FBDEV_EMULATION config DRM_FBDEV_EMULATION
bool "Enable legacy fbdev support for your modesetting driver" bool "Enable legacy fbdev support for your modesetting driver"
depends on DRM depends on DRM

Просмотреть файл

@ -167,9 +167,10 @@ static void lt9611uxc_hpd_work(struct work_struct *work)
struct lt9611uxc *lt9611uxc = container_of(work, struct lt9611uxc, work); struct lt9611uxc *lt9611uxc = container_of(work, struct lt9611uxc, work);
bool connected; bool connected;
if (lt9611uxc->connector.dev) if (lt9611uxc->connector.dev) {
drm_kms_helper_hotplug_event(lt9611uxc->connector.dev); if (lt9611uxc->connector.dev->mode_config.funcs)
else { drm_kms_helper_hotplug_event(lt9611uxc->connector.dev);
} else {
mutex_lock(&lt9611uxc->ocm_lock); mutex_lock(&lt9611uxc->ocm_lock);
connected = lt9611uxc->hdmi_connected; connected = lt9611uxc->hdmi_connected;
@ -339,6 +340,8 @@ static int lt9611uxc_connector_init(struct drm_bridge *bridge, struct lt9611uxc
return -ENODEV; return -ENODEV;
} }
lt9611uxc->connector.polled = DRM_CONNECTOR_POLL_HPD;
drm_connector_helper_add(&lt9611uxc->connector, drm_connector_helper_add(&lt9611uxc->connector,
&lt9611uxc_bridge_connector_helper_funcs); &lt9611uxc_bridge_connector_helper_funcs);
ret = drm_connector_init(bridge->dev, &lt9611uxc->connector, ret = drm_connector_init(bridge->dev, &lt9611uxc->connector,

Просмотреть файл

@ -12,6 +12,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h> #include <drm/drm_bridge.h>
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
@ -22,6 +23,7 @@ struct lvds_codec {
struct regulator *vcc; struct regulator *vcc;
struct gpio_desc *powerdown_gpio; struct gpio_desc *powerdown_gpio;
u32 connector_type; u32 connector_type;
unsigned int bus_format;
}; };
static inline struct lvds_codec *to_lvds_codec(struct drm_bridge *bridge) static inline struct lvds_codec *to_lvds_codec(struct drm_bridge *bridge)
@ -74,12 +76,50 @@ static const struct drm_bridge_funcs funcs = {
.disable = lvds_codec_disable, .disable = lvds_codec_disable,
}; };
#define MAX_INPUT_SEL_FORMATS 1
static u32 *
lvds_codec_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
u32 output_fmt,
unsigned int *num_input_fmts)
{
struct lvds_codec *lvds_codec = to_lvds_codec(bridge);
u32 *input_fmts;
*num_input_fmts = 0;
input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts),
GFP_KERNEL);
if (!input_fmts)
return NULL;
input_fmts[0] = lvds_codec->bus_format;
*num_input_fmts = MAX_INPUT_SEL_FORMATS;
return input_fmts;
}
static const struct drm_bridge_funcs funcs_decoder = {
.attach = lvds_codec_attach,
.enable = lvds_codec_enable,
.disable = lvds_codec_disable,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_get_input_bus_fmts = lvds_codec_atomic_get_input_bus_fmts,
};
static int lvds_codec_probe(struct platform_device *pdev) static int lvds_codec_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *panel_node; struct device_node *panel_node;
struct device_node *bus_node;
struct drm_panel *panel; struct drm_panel *panel;
struct lvds_codec *lvds_codec; struct lvds_codec *lvds_codec;
const char *mapping;
int ret;
lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL); lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL);
if (!lvds_codec) if (!lvds_codec)
@ -119,13 +159,47 @@ static int lvds_codec_probe(struct platform_device *pdev)
if (IS_ERR(lvds_codec->panel_bridge)) if (IS_ERR(lvds_codec->panel_bridge))
return PTR_ERR(lvds_codec->panel_bridge); return PTR_ERR(lvds_codec->panel_bridge);
lvds_codec->bridge.funcs = &funcs;
/*
* Decoder input LVDS format is a property of the decoder chip or even
* its strapping. Handle data-mapping the same way lvds-panel does. In
* case data-mapping is not present, do nothing, since there are still
* legacy bindings which do not specify this property.
*/
if (lvds_codec->connector_type != DRM_MODE_CONNECTOR_LVDS) {
bus_node = of_graph_get_endpoint_by_regs(dev->of_node, 0, 0);
if (!bus_node) {
dev_dbg(dev, "bus DT node not found\n");
return -ENXIO;
}
ret = of_property_read_string(bus_node, "data-mapping",
&mapping);
of_node_put(bus_node);
if (ret < 0) {
dev_warn(dev, "missing 'data-mapping' DT property\n");
} else {
if (!strcmp(mapping, "jeida-18")) {
lvds_codec->bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG;
} else if (!strcmp(mapping, "jeida-24")) {
lvds_codec->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA;
} else if (!strcmp(mapping, "vesa-24")) {
lvds_codec->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG;
} else {
dev_err(dev, "invalid 'data-mapping' DT property\n");
return -EINVAL;
}
lvds_codec->bridge.funcs = &funcs_decoder;
}
}
/* /*
* The panel_bridge bridge is attached to the panel's of_node, * The panel_bridge bridge is attached to the panel's of_node,
* but we need a bridge attached to our of_node for our user * but we need a bridge attached to our of_node for our user
* to look up. * to look up.
*/ */
lvds_codec->bridge.of_node = dev->of_node; lvds_codec->bridge.of_node = dev->of_node;
lvds_codec->bridge.funcs = &funcs;
drm_bridge_add(&lvds_codec->bridge); drm_bridge_add(&lvds_codec->bridge);
platform_set_drvdata(pdev, lvds_codec); platform_set_drvdata(pdev, lvds_codec);

Просмотреть файл

@ -939,6 +939,40 @@ static void nwl_dsi_bridge_detach(struct drm_bridge *bridge)
drm_of_panel_bridge_remove(dsi->dev->of_node, 1, 0); drm_of_panel_bridge_remove(dsi->dev->of_node, 1, 0);
} }
static u32 *nwl_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
u32 output_fmt,
unsigned int *num_input_fmts)
{
u32 *input_fmts, input_fmt;
*num_input_fmts = 0;
switch (output_fmt) {
/* If MEDIA_BUS_FMT_FIXED is tested, return default bus format */
case MEDIA_BUS_FMT_FIXED:
input_fmt = MEDIA_BUS_FMT_RGB888_1X24;
break;
case MEDIA_BUS_FMT_RGB888_1X24:
case MEDIA_BUS_FMT_RGB666_1X18:
case MEDIA_BUS_FMT_RGB565_1X16:
input_fmt = output_fmt;
break;
default:
return NULL;
}
input_fmts = kcalloc(1, sizeof(*input_fmts), GFP_KERNEL);
if (!input_fmts)
return NULL;
input_fmts[0] = input_fmt;
*num_input_fmts = 1;
return input_fmts;
}
static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = { static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
@ -946,6 +980,7 @@ static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = {
.atomic_check = nwl_dsi_bridge_atomic_check, .atomic_check = nwl_dsi_bridge_atomic_check,
.atomic_enable = nwl_dsi_bridge_atomic_enable, .atomic_enable = nwl_dsi_bridge_atomic_enable,
.atomic_disable = nwl_dsi_bridge_atomic_disable, .atomic_disable = nwl_dsi_bridge_atomic_disable,
.atomic_get_input_bus_fmts = nwl_bridge_atomic_get_input_bus_fmts,
.mode_set = nwl_dsi_bridge_mode_set, .mode_set = nwl_dsi_bridge_mode_set,
.mode_valid = nwl_dsi_bridge_mode_valid, .mode_valid = nwl_dsi_bridge_mode_valid,
.attach = nwl_dsi_bridge_attach, .attach = nwl_dsi_bridge_attach,

Просмотреть файл

@ -288,6 +288,19 @@ err_dsi_attach:
return ret; return ret;
} }
static void sn65dsi83_detach(struct drm_bridge *bridge)
{
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
if (!ctx->dsi)
return;
mipi_dsi_detach(ctx->dsi);
mipi_dsi_device_unregister(ctx->dsi);
drm_bridge_remove(&ctx->bridge);
ctx->dsi = NULL;
}
static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge, static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state) struct drm_bridge_state *old_bridge_state)
{ {
@ -583,6 +596,7 @@ sn65dsi83_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
static const struct drm_bridge_funcs sn65dsi83_funcs = { static const struct drm_bridge_funcs sn65dsi83_funcs = {
.attach = sn65dsi83_attach, .attach = sn65dsi83_attach,
.detach = sn65dsi83_detach,
.atomic_pre_enable = sn65dsi83_atomic_pre_enable, .atomic_pre_enable = sn65dsi83_atomic_pre_enable,
.atomic_enable = sn65dsi83_atomic_enable, .atomic_enable = sn65dsi83_atomic_enable,
.atomic_disable = sn65dsi83_atomic_disable, .atomic_disable = sn65dsi83_atomic_disable,
@ -697,9 +711,6 @@ static int sn65dsi83_remove(struct i2c_client *client)
{ {
struct sn65dsi83 *ctx = i2c_get_clientdata(client); struct sn65dsi83 *ctx = i2c_get_clientdata(client);
mipi_dsi_detach(ctx->dsi);
mipi_dsi_device_unregister(ctx->dsi);
drm_bridge_remove(&ctx->bridge);
of_node_put(ctx->host_node); of_node_put(ctx->host_node);
return 0; return 0;

Просмотреть файл

@ -625,6 +625,8 @@ int drm_connector_register_all(struct drm_device *dev)
* *
* In contrast to the other drm_get_*_name functions this one here returns a * In contrast to the other drm_get_*_name functions this one here returns a
* const pointer and hence is threadsafe. * const pointer and hence is threadsafe.
*
* Returns: connector status string
*/ */
const char *drm_get_connector_status_name(enum drm_connector_status status) const char *drm_get_connector_status_name(enum drm_connector_status status)
{ {
@ -707,7 +709,7 @@ __drm_connector_put_safe(struct drm_connector *conn)
* drm_connector_list_iter_next - return next connector * drm_connector_list_iter_next - return next connector
* @iter: connector_list iterator * @iter: connector_list iterator
* *
* Returns the next connector for @iter, or NULL when the list walk has * Returns: the next connector for @iter, or NULL when the list walk has
* completed. * completed.
*/ */
struct drm_connector * struct drm_connector *
@ -780,6 +782,8 @@ static const struct drm_prop_enum_list drm_subpixel_enum_list[] = {
* *
* Note you could abuse this and return something out of bounds, but that * Note you could abuse this and return something out of bounds, but that
* would be a caller error. No unscrubbed user data should make it here. * would be a caller error. No unscrubbed user data should make it here.
*
* Returns: string describing an enumerated subpixel property
*/ */
const char *drm_get_subpixel_order_name(enum subpixel_order order) const char *drm_get_subpixel_order_name(enum subpixel_order order)
{ {
@ -809,6 +813,9 @@ static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
* Store the supported bus formats in display info structure. * Store the supported bus formats in display info structure.
* See MEDIA_BUS_FMT_* definitions in include/uapi/linux/media-bus-format.h for * See MEDIA_BUS_FMT_* definitions in include/uapi/linux/media-bus-format.h for
* a full list of available formats. * a full list of available formats.
*
* Returns:
* 0 on success or a negative error code on failure.
*/ */
int drm_display_info_set_bus_formats(struct drm_display_info *info, int drm_display_info_set_bus_formats(struct drm_display_info *info,
const u32 *formats, const u32 *formats,
@ -1326,6 +1333,8 @@ int drm_connector_create_standard_properties(struct drm_device *dev)
* @dev: DRM device * @dev: DRM device
* *
* Called by a driver the first time a DVI-I connector is made. * Called by a driver the first time a DVI-I connector is made.
*
* Returns: %0
*/ */
int drm_mode_create_dvi_i_properties(struct drm_device *dev) int drm_mode_create_dvi_i_properties(struct drm_device *dev)
{ {
@ -1397,6 +1406,8 @@ EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property);
* Game: * Game:
* Content type is game * Content type is game
* *
* The meaning of each content type is defined in CTA-861-G table 15.
*
* Drivers can set up this property by calling * Drivers can set up this property by calling
* drm_connector_attach_content_type_property(). Decoding to * drm_connector_attach_content_type_property(). Decoding to
* infoframe values is done through drm_hdmi_avi_infoframe_content_type(). * infoframe values is done through drm_hdmi_avi_infoframe_content_type().
@ -1407,6 +1418,8 @@ EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property);
* @connector: connector to attach content type property on. * @connector: connector to attach content type property on.
* *
* Called by a driver the first time a HDMI connector is made. * Called by a driver the first time a HDMI connector is made.
*
* Returns: %0
*/ */
int drm_connector_attach_content_type_property(struct drm_connector *connector) int drm_connector_attach_content_type_property(struct drm_connector *connector)
{ {
@ -1487,6 +1500,9 @@ EXPORT_SYMBOL(drm_connector_attach_tv_margin_properties);
* creates the TV margin properties for a given device. No need to call this * creates the TV margin properties for a given device. No need to call this
* function for an SDTV connector, it's already called from * function for an SDTV connector, it's already called from
* drm_mode_create_tv_properties(). * drm_mode_create_tv_properties().
*
* Returns:
* 0 on success or a negative error code on failure.
*/ */
int drm_mode_create_tv_margin_properties(struct drm_device *dev) int drm_mode_create_tv_margin_properties(struct drm_device *dev)
{ {
@ -1527,6 +1543,9 @@ EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
* the TV specific connector properties for a given device. Caller is * the TV specific connector properties for a given device. Caller is
* responsible for allocating a list of format names and passing them to * responsible for allocating a list of format names and passing them to
* this routine. * this routine.
*
* Returns:
* 0 on success or a negative error code on failure.
*/ */
int drm_mode_create_tv_properties(struct drm_device *dev, int drm_mode_create_tv_properties(struct drm_device *dev,
unsigned int num_modes, unsigned int num_modes,
@ -1622,6 +1641,8 @@ EXPORT_SYMBOL(drm_mode_create_tv_properties);
* Atomic drivers should use drm_connector_attach_scaling_mode_property() * Atomic drivers should use drm_connector_attach_scaling_mode_property()
* instead to correctly assign &drm_connector_state.scaling_mode * instead to correctly assign &drm_connector_state.scaling_mode
* in the atomic state. * in the atomic state.
*
* Returns: %0
*/ */
int drm_mode_create_scaling_mode_property(struct drm_device *dev) int drm_mode_create_scaling_mode_property(struct drm_device *dev)
{ {
@ -1939,6 +1960,9 @@ EXPORT_SYMBOL(drm_mode_create_content_type_property);
* @dev: DRM device * @dev: DRM device
* *
* Create the suggested x/y offset property for connectors. * Create the suggested x/y offset property for connectors.
*
* Returns:
* 0 on success or a negative error code on failure.
*/ */
int drm_mode_create_suggested_offset_properties(struct drm_device *dev) int drm_mode_create_suggested_offset_properties(struct drm_device *dev)
{ {
@ -2312,8 +2336,8 @@ int drm_connector_set_panel_orientation(
EXPORT_SYMBOL(drm_connector_set_panel_orientation); EXPORT_SYMBOL(drm_connector_set_panel_orientation);
/** /**
* drm_connector_set_panel_orientation_with_quirk - * drm_connector_set_panel_orientation_with_quirk - set the
* set the connector's panel_orientation after checking for quirks * connector's panel_orientation after checking for quirks
* @connector: connector for which to init the panel-orientation property. * @connector: connector for which to init the panel-orientation property.
* @panel_orientation: drm_panel_orientation value to set * @panel_orientation: drm_panel_orientation value to set
* @width: width in pixels of the panel, used for panel quirk detection * @width: width in pixels of the panel, used for panel quirk detection
@ -2597,7 +2621,7 @@ struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode)
/** /**
* drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector
* @connector: connector to report the event on * @connector_fwnode: fwnode_handle to report the event on
* *
* On some hardware a hotplug event notification may come from outside the display * On some hardware a hotplug event notification may come from outside the display
* driver / device. An example of this is some USB Type-C setups where the hardware * driver / device. An example of this is some USB Type-C setups where the hardware

Просмотреть файл

@ -1340,31 +1340,15 @@ int drm_gem_fence_array_add_implicit(struct xarray *fence_array,
struct drm_gem_object *obj, struct drm_gem_object *obj,
bool write) bool write)
{ {
int ret; struct dma_resv_iter cursor;
struct dma_fence **fences; struct dma_fence *fence;
unsigned int i, fence_count; int ret = 0;
if (!write) { dma_resv_for_each_fence(&cursor, obj->resv, write, fence) {
struct dma_fence *fence = ret = drm_gem_fence_array_add(fence_array, fence);
dma_resv_get_excl_unlocked(obj->resv);
return drm_gem_fence_array_add(fence_array, fence);
}
ret = dma_resv_get_fences(obj->resv, NULL,
&fence_count, &fences);
if (ret || !fence_count)
return ret;
for (i = 0; i < fence_count; i++) {
ret = drm_gem_fence_array_add(fence_array, fences[i]);
if (ret) if (ret)
break; break;
} }
for (; i < fence_count; i++)
dma_fence_put(fences[i]);
kfree(fences);
return ret; return ret;
} }
EXPORT_SYMBOL(drm_gem_fence_array_add_implicit); EXPORT_SYMBOL(drm_gem_fence_array_add_implicit);

Просмотреть файл

@ -25,6 +25,7 @@
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_device.h> #include <drm/drm_device.h>
#include <drm/drm_modeset_lock.h> #include <drm/drm_modeset_lock.h>
#include <drm/drm_print.h>
/** /**
* DOC: kms locking * DOC: kms locking
@ -77,6 +78,45 @@
static DEFINE_WW_CLASS(crtc_ww_class); static DEFINE_WW_CLASS(crtc_ww_class);
#if IS_ENABLED(CONFIG_DRM_DEBUG_MODESET_LOCK)
static noinline depot_stack_handle_t __stack_depot_save(void)
{
unsigned long entries[8];
unsigned int n;
n = stack_trace_save(entries, ARRAY_SIZE(entries), 1);
return stack_depot_save(entries, n, GFP_NOWAIT | __GFP_NOWARN);
}
static void __stack_depot_print(depot_stack_handle_t stack_depot)
{
struct drm_printer p = drm_debug_printer("drm_modeset_lock");
unsigned long *entries;
unsigned int nr_entries;
char *buf;
buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN);
if (!buf)
return;
nr_entries = stack_depot_fetch(stack_depot, &entries);
stack_trace_snprint(buf, PAGE_SIZE, entries, nr_entries, 2);
drm_printf(&p, "attempting to lock a contended lock without backoff:\n%s", buf);
kfree(buf);
}
#else /* CONFIG_DRM_DEBUG_MODESET_LOCK */
static depot_stack_handle_t __stack_depot_save(void)
{
return 0;
}
static void __stack_depot_print(depot_stack_handle_t stack_depot)
{
}
#endif /* CONFIG_DRM_DEBUG_MODESET_LOCK */
/** /**
* drm_modeset_lock_all - take all modeset locks * drm_modeset_lock_all - take all modeset locks
* @dev: DRM device * @dev: DRM device
@ -225,7 +265,9 @@ EXPORT_SYMBOL(drm_modeset_acquire_fini);
*/ */
void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx) void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx)
{ {
WARN_ON(ctx->contended); if (WARN_ON(ctx->contended))
__stack_depot_print(ctx->stack_depot);
while (!list_empty(&ctx->locked)) { while (!list_empty(&ctx->locked)) {
struct drm_modeset_lock *lock; struct drm_modeset_lock *lock;
@ -243,7 +285,8 @@ static inline int modeset_lock(struct drm_modeset_lock *lock,
{ {
int ret; int ret;
WARN_ON(ctx->contended); if (WARN_ON(ctx->contended))
__stack_depot_print(ctx->stack_depot);
if (ctx->trylock_only) { if (ctx->trylock_only) {
lockdep_assert_held(&ctx->ww_ctx); lockdep_assert_held(&ctx->ww_ctx);
@ -274,6 +317,7 @@ static inline int modeset_lock(struct drm_modeset_lock *lock,
ret = 0; ret = 0;
} else if (ret == -EDEADLK) { } else if (ret == -EDEADLK) {
ctx->contended = lock; ctx->contended = lock;
ctx->stack_depot = __stack_depot_save();
} }
return ret; return ret;
@ -296,6 +340,7 @@ int drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx)
struct drm_modeset_lock *contended = ctx->contended; struct drm_modeset_lock *contended = ctx->contended;
ctx->contended = NULL; ctx->contended = NULL;
ctx->stack_depot = 0;
if (WARN_ON(!contended)) if (WARN_ON(!contended))
return 0; return 0;

Просмотреть файл

@ -123,7 +123,6 @@ static int drm_plane_helper_check_update(struct drm_plane *plane,
.crtc_w = drm_rect_width(dst), .crtc_w = drm_rect_width(dst),
.crtc_h = drm_rect_height(dst), .crtc_h = drm_rect_height(dst),
.rotation = rotation, .rotation = rotation,
.visible = *visible,
}; };
struct drm_crtc_state crtc_state = { struct drm_crtc_state crtc_state = {
.crtc = crtc, .crtc = crtc,

Просмотреть файл

@ -1537,38 +1537,14 @@ i915_request_await_object(struct i915_request *to,
struct drm_i915_gem_object *obj, struct drm_i915_gem_object *obj,
bool write) bool write)
{ {
struct dma_fence *excl; struct dma_resv_iter cursor;
struct dma_fence *fence;
int ret = 0; int ret = 0;
if (write) { dma_resv_for_each_fence(&cursor, obj->base.resv, write, fence) {
struct dma_fence **shared; ret = i915_request_await_dma_fence(to, fence);
unsigned int count, i;
ret = dma_resv_get_fences(obj->base.resv, &excl, &count,
&shared);
if (ret) if (ret)
return ret; break;
for (i = 0; i < count; i++) {
ret = i915_request_await_dma_fence(to, shared[i]);
if (ret)
break;
dma_fence_put(shared[i]);
}
for (; i < count; i++)
dma_fence_put(shared[i]);
kfree(shared);
} else {
excl = dma_resv_get_excl_unlocked(obj->base.resv);
}
if (excl) {
if (ret == 0)
ret = i915_request_await_dma_fence(to, excl);
dma_fence_put(excl);
} }
return ret; return ret;

Просмотреть файл

@ -88,7 +88,7 @@ static void mxsfb_set_formats(struct mxsfb_drm_private *mxsfb,
ctrl |= CTRL_BUS_WIDTH_24; ctrl |= CTRL_BUS_WIDTH_24;
break; break;
default: default:
dev_err(drm->dev, "Unknown media bus format %d\n", bus_format); dev_err(drm->dev, "Unknown media bus format 0x%x\n", bus_format);
break; break;
} }
@ -362,6 +362,12 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
drm_atomic_get_new_bridge_state(state, drm_atomic_get_new_bridge_state(state,
mxsfb->bridge); mxsfb->bridge);
bus_format = bridge_state->input_bus_cfg.format; bus_format = bridge_state->input_bus_cfg.format;
if (bus_format == MEDIA_BUS_FMT_FIXED) {
dev_warn_once(drm->dev,
"Bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
"Please fix bridge driver by handling atomic_get_input_bus_fmts.\n");
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
}
} }
/* If there is no bridge, use bus format from connector */ /* If there is no bridge, use bus format from connector */

Просмотреть файл

@ -1249,7 +1249,6 @@ nouveau_ttm_tt_populate(struct ttm_device *bdev,
{ {
struct ttm_tt *ttm_dma = (void *)ttm; struct ttm_tt *ttm_dma = (void *)ttm;
struct nouveau_drm *drm; struct nouveau_drm *drm;
struct device *dev;
bool slave = !!(ttm->page_flags & TTM_TT_FLAG_EXTERNAL); bool slave = !!(ttm->page_flags & TTM_TT_FLAG_EXTERNAL);
if (ttm_tt_is_populated(ttm)) if (ttm_tt_is_populated(ttm))
@ -1262,7 +1261,6 @@ nouveau_ttm_tt_populate(struct ttm_device *bdev,
} }
drm = nouveau_bdev(bdev); drm = nouveau_bdev(bdev);
dev = drm->dev->dev;
return ttm_pool_alloc(&drm->ttm.bdev.pool, ttm, ctx); return ttm_pool_alloc(&drm->ttm.bdev.pool, ttm, ctx);
} }
@ -1272,7 +1270,6 @@ nouveau_ttm_tt_unpopulate(struct ttm_device *bdev,
struct ttm_tt *ttm) struct ttm_tt *ttm)
{ {
struct nouveau_drm *drm; struct nouveau_drm *drm;
struct device *dev;
bool slave = !!(ttm->page_flags & TTM_TT_FLAG_EXTERNAL); bool slave = !!(ttm->page_flags & TTM_TT_FLAG_EXTERNAL);
if (slave) if (slave)
@ -1281,7 +1278,6 @@ nouveau_ttm_tt_unpopulate(struct ttm_device *bdev,
nouveau_ttm_tt_unbind(bdev, ttm); nouveau_ttm_tt_unbind(bdev, ttm);
drm = nouveau_bdev(bdev); drm = nouveau_bdev(bdev);
dev = drm->dev->dev;
return ttm_pool_free(&drm->ttm.bdev.pool, ttm); return ttm_pool_free(&drm->ttm.bdev.pool, ttm);
} }

Просмотреть файл

@ -337,7 +337,7 @@ nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains,
struct ttm_buffer_object *bo = &nvbo->bo; struct ttm_buffer_object *bo = &nvbo->bo;
uint32_t domains = valid_domains & nvbo->valid_domains & uint32_t domains = valid_domains & nvbo->valid_domains &
(write_domains ? write_domains : read_domains); (write_domains ? write_domains : read_domains);
uint32_t pref_domains = 0;; uint32_t pref_domains = 0;
if (!domains) if (!domains)
return -EINVAL; return -EINVAL;

Просмотреть файл

@ -21,7 +21,6 @@
*/ */
#include "priv.h" #include "priv.h"
#include "priv.h"
#include <core/firmware.h> #include <core/firmware.h>
static void * static void *

Просмотреть файл

@ -299,7 +299,7 @@ nvkm_uvmm_mthd_page(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
page = uvmm->vmm->func->page; page = uvmm->vmm->func->page;
for (nr = 0; page[nr].shift; nr++); for (nr = 0; page[nr].shift; nr++);
if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { if (!(nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
if ((index = args->v0.index) >= nr) if ((index = args->v0.index) >= nr)
return -EINVAL; return -EINVAL;
type = page[index].type; type = page[index].type;

Просмотреть файл

@ -488,7 +488,7 @@ gp100_vmm_fault_cancel(struct nvkm_vmm *vmm, void *argv, u32 argc)
struct gp100_vmm_fault_cancel_v0 v0; struct gp100_vmm_fault_cancel_v0 v0;
} *args = argv; } *args = argv;
int ret = -ENOSYS; int ret = -ENOSYS;
u32 inst, aper; u32 aper;
if ((ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) if ((ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false)))
return ret; return ret;
@ -502,7 +502,7 @@ gp100_vmm_fault_cancel(struct nvkm_vmm *vmm, void *argv, u32 argc)
args->v0.inst |= 0x80000000; args->v0.inst |= 0x80000000;
if (!WARN_ON(nvkm_gr_ctxsw_pause(device))) { if (!WARN_ON(nvkm_gr_ctxsw_pause(device))) {
if ((inst = nvkm_gr_ctxsw_inst(device)) == args->v0.inst) { if (nvkm_gr_ctxsw_inst(device) == args->v0.inst) {
gf100_vmm_invalidate(vmm, 0x0000001b gf100_vmm_invalidate(vmm, 0x0000001b
/* CANCEL_TARGETED. */ | /* CANCEL_TARGETED. */ |
(args->v0.hub << 20) | (args->v0.hub << 20) |

Просмотреть файл

@ -520,6 +520,16 @@ config DRM_PANEL_SHARP_LS043T1LE01
Say Y here if you want to enable support for Sharp LS043T1LE01 qHD Say Y here if you want to enable support for Sharp LS043T1LE01 qHD
(540x960) DSI panel as found on the Qualcomm APQ8074 Dragonboard (540x960) DSI panel as found on the Qualcomm APQ8074 Dragonboard
config DRM_PANEL_SHARP_LS060T1SX01
tristate "Sharp LS060T1SX01 FullHD video mode panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable support for Sharp LS060T1SX01 6.0"
FullHD (1080x1920) DSI panel as found in Dragonboard Display Adapter
Bundle.
config DRM_PANEL_SITRONIX_ST7701 config DRM_PANEL_SITRONIX_ST7701
tristate "Sitronix ST7701 panel driver" tristate "Sitronix ST7701 panel driver"
depends on OF depends on OF

Просмотреть файл

@ -53,6 +53,7 @@ obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o
obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
obj-$(CONFIG_DRM_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o obj-$(CONFIG_DRM_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o
obj-$(CONFIG_DRM_PANEL_SHARP_LS060T1SX01) += panel-sharp-ls060t1sx01.o
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7701) += panel-sitronix-st7701.o obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7701) += panel-sitronix-st7701.o
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7703) += panel-sitronix-st7703.o obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7703) += panel-sitronix-st7703.o
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o

Просмотреть файл

@ -8,6 +8,7 @@
#include <linux/backlight.h> #include <linux/backlight.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/media-bus-format.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
@ -220,6 +221,10 @@ static const struct drm_display_mode default_mode_ys = {
.height_mm = 130, .height_mm = 130,
}; };
static const u32 mantix_bus_formats[] = {
MEDIA_BUS_FMT_RGB888_1X24,
};
static int mantix_get_modes(struct drm_panel *panel, static int mantix_get_modes(struct drm_panel *panel,
struct drm_connector *connector) struct drm_connector *connector)
{ {
@ -241,6 +246,10 @@ static int mantix_get_modes(struct drm_panel *panel,
connector->display_info.height_mm = mode->height_mm; connector->display_info.height_mm = mode->height_mm;
drm_mode_probed_add(connector, mode); drm_mode_probed_add(connector, mode);
drm_display_info_set_bus_formats(&connector->display_info,
mantix_bus_formats,
ARRAY_SIZE(mantix_bus_formats));
return 1; return 1;
} }

Просмотреть файл

@ -116,7 +116,8 @@ static int s6e63m0_dsi_probe(struct mipi_dsi_device *dsi)
static int s6e63m0_dsi_remove(struct mipi_dsi_device *dsi) static int s6e63m0_dsi_remove(struct mipi_dsi_device *dsi)
{ {
mipi_dsi_detach(dsi); mipi_dsi_detach(dsi);
return s6e63m0_remove(&dsi->dev); s6e63m0_remove(&dsi->dev);
return 0;
} }
static const struct of_device_id s6e63m0_dsi_of_match[] = { static const struct of_device_id s6e63m0_dsi_of_match[] = {

Просмотреть файл

@ -64,7 +64,8 @@ static int s6e63m0_spi_probe(struct spi_device *spi)
static int s6e63m0_spi_remove(struct spi_device *spi) static int s6e63m0_spi_remove(struct spi_device *spi)
{ {
return s6e63m0_remove(&spi->dev); s6e63m0_remove(&spi->dev);
return 0;
} }
static const struct of_device_id s6e63m0_spi_of_match[] = { static const struct of_device_id s6e63m0_spi_of_match[] = {

Просмотреть файл

@ -749,13 +749,11 @@ int s6e63m0_probe(struct device *dev, void *trsp,
} }
EXPORT_SYMBOL_GPL(s6e63m0_probe); EXPORT_SYMBOL_GPL(s6e63m0_probe);
int s6e63m0_remove(struct device *dev) void s6e63m0_remove(struct device *dev)
{ {
struct s6e63m0 *ctx = dev_get_drvdata(dev); struct s6e63m0 *ctx = dev_get_drvdata(dev);
drm_panel_remove(&ctx->panel); drm_panel_remove(&ctx->panel);
return 0;
} }
EXPORT_SYMBOL_GPL(s6e63m0_remove); EXPORT_SYMBOL_GPL(s6e63m0_remove);

Просмотреть файл

@ -35,6 +35,6 @@ int s6e63m0_probe(struct device *dev, void *trsp,
const u8 *data, const u8 *data,
size_t len), size_t len),
bool dsi_mode); bool dsi_mode);
int s6e63m0_remove(struct device *dev); void s6e63m0_remove(struct device *dev);
#endif /* _PANEL_SAMSUNG_S6E63M0_H */ #endif /* _PANEL_SAMSUNG_S6E63M0_H */

Просмотреть файл

@ -0,0 +1,333 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2021 Linaro Ltd.
* Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
*/
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <video/mipi_display.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>
struct sharp_ls060 {
struct drm_panel panel;
struct mipi_dsi_device *dsi;
struct regulator *vddi_supply;
struct regulator *vddh_supply;
struct regulator *avdd_supply;
struct regulator *avee_supply;
struct gpio_desc *reset_gpio;
bool prepared;
};
static inline struct sharp_ls060 *to_sharp_ls060(struct drm_panel *panel)
{
return container_of(panel, struct sharp_ls060, panel);
}
#define dsi_dcs_write_seq(dsi, seq...) ({ \
static const u8 d[] = { seq }; \
\
mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
})
static void sharp_ls060_reset(struct sharp_ls060 *ctx)
{
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
usleep_range(10000, 11000);
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
usleep_range(10000, 11000);
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
usleep_range(10000, 11000);
}
static int sharp_ls060_on(struct sharp_ls060 *ctx)
{
struct mipi_dsi_device *dsi = ctx->dsi;
struct device *dev = &dsi->dev;
int ret;
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
ret = dsi_dcs_write_seq(dsi, 0xbb, 0x13);
if (ret < 0) {
dev_err(dev, "Failed to send command: %d\n", ret);
return ret;
}
ret = dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_MEMORY_START);
if (ret < 0) {
dev_err(dev, "Failed to send command: %d\n", ret);
return ret;
}
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
if (ret < 0) {
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
return ret;
}
msleep(120);
ret = mipi_dsi_dcs_set_display_on(dsi);
if (ret < 0) {
dev_err(dev, "Failed to set display on: %d\n", ret);
return ret;
}
msleep(50);
return 0;
}
static int sharp_ls060_off(struct sharp_ls060 *ctx)
{
struct mipi_dsi_device *dsi = ctx->dsi;
struct device *dev = &dsi->dev;
int ret;
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
ret = mipi_dsi_dcs_set_display_off(dsi);
if (ret < 0) {
dev_err(dev, "Failed to set display off: %d\n", ret);
return ret;
}
usleep_range(2000, 3000);
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
if (ret < 0) {
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
return ret;
}
msleep(121);
return 0;
}
static int sharp_ls060_prepare(struct drm_panel *panel)
{
struct sharp_ls060 *ctx = to_sharp_ls060(panel);
struct device *dev = &ctx->dsi->dev;
int ret;
if (ctx->prepared)
return 0;
ret = regulator_enable(ctx->vddi_supply);
if (ret < 0)
return ret;
ret = regulator_enable(ctx->avdd_supply);
if (ret < 0)
goto err_avdd;
usleep_range(1000, 2000);
ret = regulator_enable(ctx->avee_supply);
if (ret < 0)
goto err_avee;
usleep_range(10000, 11000);
ret = regulator_enable(ctx->vddh_supply);
if (ret < 0)
goto err_vddh;
usleep_range(10000, 11000);
sharp_ls060_reset(ctx);
ret = sharp_ls060_on(ctx);
if (ret < 0) {
dev_err(dev, "Failed to initialize panel: %d\n", ret);
goto err_on;
}
ctx->prepared = true;
return 0;
err_on:
regulator_disable(ctx->vddh_supply);
usleep_range(10000, 11000);
err_vddh:
regulator_disable(ctx->avee_supply);
err_avee:
regulator_disable(ctx->avdd_supply);
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
err_avdd:
regulator_disable(ctx->vddi_supply);
return ret;
}
static int sharp_ls060_unprepare(struct drm_panel *panel)
{
struct sharp_ls060 *ctx = to_sharp_ls060(panel);
struct device *dev = &ctx->dsi->dev;
int ret;
if (!ctx->prepared)
return 0;
ret = sharp_ls060_off(ctx);
if (ret < 0)
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
regulator_disable(ctx->vddh_supply);
usleep_range(10000, 11000);
regulator_disable(ctx->avee_supply);
regulator_disable(ctx->avdd_supply);
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
regulator_disable(ctx->vddi_supply);
ctx->prepared = false;
return 0;
}
static const struct drm_display_mode sharp_ls060_mode = {
.clock = (1080 + 96 + 16 + 64) * (1920 + 4 + 1 + 16) * 60 / 1000,
.hdisplay = 1080,
.hsync_start = 1080 + 96,
.hsync_end = 1080 + 96 + 16,
.htotal = 1080 + 96 + 16 + 64,
.vdisplay = 1920,
.vsync_start = 1920 + 4,
.vsync_end = 1920 + 4 + 1,
.vtotal = 1920 + 4 + 1 + 16,
.width_mm = 75,
.height_mm = 132,
};
static int sharp_ls060_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
struct drm_display_mode *mode;
mode = drm_mode_duplicate(connector->dev, &sharp_ls060_mode);
if (!mode)
return -ENOMEM;
drm_mode_set_name(mode);
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
connector->display_info.width_mm = mode->width_mm;
connector->display_info.height_mm = mode->height_mm;
drm_mode_probed_add(connector, mode);
return 1;
}
static const struct drm_panel_funcs sharp_ls060_panel_funcs = {
.prepare = sharp_ls060_prepare,
.unprepare = sharp_ls060_unprepare,
.get_modes = sharp_ls060_get_modes,
};
static int sharp_ls060_probe(struct mipi_dsi_device *dsi)
{
struct device *dev = &dsi->dev;
struct sharp_ls060 *ctx;
int ret;
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ctx->vddi_supply = devm_regulator_get(dev, "vddi");
if (IS_ERR(ctx->vddi_supply))
return PTR_ERR(ctx->vddi_supply);
ctx->vddh_supply = devm_regulator_get(dev, "vddh");
if (IS_ERR(ctx->vddh_supply))
return PTR_ERR(ctx->vddh_supply);
ctx->avdd_supply = devm_regulator_get(dev, "avdd");
if (IS_ERR(ctx->avdd_supply))
return PTR_ERR(ctx->avdd_supply);
ctx->avee_supply = devm_regulator_get(dev, "avee");
if (IS_ERR(ctx->avee_supply))
return PTR_ERR(ctx->avee_supply);
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ctx->reset_gpio))
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
"Failed to get reset-gpios\n");
ctx->dsi = dsi;
mipi_dsi_set_drvdata(dsi, ctx);
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_NO_EOT_PACKET |
MIPI_DSI_CLOCK_NON_CONTINUOUS;
drm_panel_init(&ctx->panel, dev, &sharp_ls060_panel_funcs,
DRM_MODE_CONNECTOR_DSI);
ret = drm_panel_of_backlight(&ctx->panel);
if (ret)
return dev_err_probe(dev, ret, "Failed to get backlight\n");
drm_panel_add(&ctx->panel);
ret = mipi_dsi_attach(dsi);
if (ret < 0) {
dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
drm_panel_remove(&ctx->panel);
return ret;
}
return 0;
}
static int sharp_ls060_remove(struct mipi_dsi_device *dsi)
{
struct sharp_ls060 *ctx = mipi_dsi_get_drvdata(dsi);
int ret;
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
drm_panel_remove(&ctx->panel);
return 0;
}
static const struct of_device_id sharp_ls060t1sx01_of_match[] = {
{ .compatible = "sharp,ls060t1sx01" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sharp_ls060t1sx01_of_match);
static struct mipi_dsi_driver sharp_ls060_driver = {
.probe = sharp_ls060_probe,
.remove = sharp_ls060_remove,
.driver = {
.name = "panel-sharp-ls060t1sx01",
.of_match_table = sharp_ls060t1sx01_of_match,
},
};
module_mipi_dsi_driver(sharp_ls060_driver);
MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>");
MODULE_DESCRIPTION("DRM driver for Sharp LS060T1SX01 1080p video mode dsi panel");
MODULE_LICENSE("GPL v2");

Просмотреть файл

@ -2370,6 +2370,38 @@ static const struct panel_desc logictechno_lt170410_2whc = {
.connector_type = DRM_MODE_CONNECTOR_LVDS, .connector_type = DRM_MODE_CONNECTOR_LVDS,
}; };
static const struct drm_display_mode logictechno_lttd800480070_l2rt_mode = {
.clock = 33000,
.hdisplay = 800,
.hsync_start = 800 + 112,
.hsync_end = 800 + 112 + 3,
.htotal = 800 + 112 + 3 + 85,
.vdisplay = 480,
.vsync_start = 480 + 38,
.vsync_end = 480 + 38 + 3,
.vtotal = 480 + 38 + 3 + 29,
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
};
static const struct panel_desc logictechno_lttd800480070_l2rt = {
.modes = &logictechno_lttd800480070_l2rt_mode,
.num_modes = 1,
.bpc = 8,
.size = {
.width = 154,
.height = 86,
},
.delay = {
.prepare = 45,
.enable = 100,
.disable = 100,
.unprepare = 45
},
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
.bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE,
.connector_type = DRM_MODE_CONNECTOR_DPI,
};
static const struct drm_display_mode logictechno_lttd800480070_l6wh_rt_mode = { static const struct drm_display_mode logictechno_lttd800480070_l6wh_rt_mode = {
.clock = 33000, .clock = 33000,
.hdisplay = 800, .hdisplay = 800,
@ -3750,6 +3782,9 @@ static const struct of_device_id platform_of_match[] = {
}, { }, {
.compatible = "logictechno,lt170410-2whc", .compatible = "logictechno,lt170410-2whc",
.data = &logictechno_lt170410_2whc, .data = &logictechno_lt170410_2whc,
}, {
.compatible = "logictechno,lttd800480070-l2rt",
.data = &logictechno_lttd800480070_l2rt,
}, { }, {
.compatible = "logictechno,lttd800480070-l6wh-rt", .compatible = "logictechno,lttd800480070-l6wh-rt",
.data = &logictechno_lttd800480070_l6wh_rt, .data = &logictechno_lttd800480070_l6wh_rt,

Просмотреть файл

@ -453,6 +453,10 @@ disable_vcc:
return ret; return ret;
} }
static const u32 mantix_bus_formats[] = {
MEDIA_BUS_FMT_RGB888_1X24,
};
static int st7703_get_modes(struct drm_panel *panel, static int st7703_get_modes(struct drm_panel *panel,
struct drm_connector *connector) struct drm_connector *connector)
{ {
@ -474,6 +478,10 @@ static int st7703_get_modes(struct drm_panel *panel,
connector->display_info.height_mm = mode->height_mm; connector->display_info.height_mm = mode->height_mm;
drm_mode_probed_add(connector, mode); drm_mode_probed_add(connector, mode);
drm_display_info_set_bus_formats(&connector->display_info,
mantix_bus_formats,
ARRAY_SIZE(mantix_bus_formats));
return 1; return 1;
} }

Просмотреть файл

@ -699,30 +699,16 @@ int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job,
struct drm_gem_object *obj, struct drm_gem_object *obj,
bool write) bool write)
{ {
struct dma_resv_iter cursor;
struct dma_fence *fence;
int ret; int ret;
struct dma_fence **fences;
unsigned int i, fence_count;
if (!write) { dma_resv_for_each_fence(&cursor, obj->resv, write, fence) {
struct dma_fence *fence = dma_resv_get_excl_unlocked(obj->resv); ret = drm_sched_job_add_dependency(job, fence);
return drm_sched_job_add_dependency(job, fence);
}
ret = dma_resv_get_fences(obj->resv, NULL, &fence_count, &fences);
if (ret || !fence_count)
return ret;
for (i = 0; i < fence_count; i++) {
ret = drm_sched_job_add_dependency(job, fences[i]);
if (ret) if (ret)
break; return ret;
} }
return 0;
for (; i < fence_count; i++)
dma_fence_put(fences[i]);
kfree(fences);
return ret;
} }
EXPORT_SYMBOL(drm_sched_job_add_implicit_dependencies); EXPORT_SYMBOL(drm_sched_job_add_implicit_dependencies);

Просмотреть файл

@ -269,23 +269,15 @@ static int ttm_bo_individualize_resv(struct ttm_buffer_object *bo)
static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo) static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo)
{ {
struct dma_resv *resv = &bo->base._resv; struct dma_resv *resv = &bo->base._resv;
struct dma_resv_list *fobj; struct dma_resv_iter cursor;
struct dma_fence *fence; struct dma_fence *fence;
int i;
rcu_read_lock();
fobj = dma_resv_shared_list(resv);
fence = dma_resv_excl_fence(resv);
if (fence && !fence->ops->signaled)
dma_fence_enable_sw_signaling(fence);
for (i = 0; fobj && i < fobj->shared_count; ++i) {
fence = rcu_dereference(fobj->shared[i]);
dma_resv_iter_begin(&cursor, resv, true);
dma_resv_for_each_fence_unlocked(&cursor, fence) {
if (!fence->ops->signaled) if (!fence->ops->signaled)
dma_fence_enable_sw_signaling(fence); dma_fence_enable_sw_signaling(fence);
} }
rcu_read_unlock(); dma_resv_iter_end(&cursor);
} }
/** /**

Просмотреть файл

@ -487,8 +487,8 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,
for (i = 0; i < se->in_sync_count; i++) { for (i = 0; i < se->in_sync_count; i++) {
struct drm_v3d_sem in; struct drm_v3d_sem in;
ret = copy_from_user(&in, handle++, sizeof(in)); if (copy_from_user(&in, handle++, sizeof(in))) {
if (ret) { ret = -EFAULT;
DRM_DEBUG("Failed to copy wait dep handle.\n"); DRM_DEBUG("Failed to copy wait dep handle.\n");
goto fail_deps; goto fail_deps;
} }
@ -609,8 +609,8 @@ v3d_get_multisync_post_deps(struct drm_file *file_priv,
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
struct drm_v3d_sem out; struct drm_v3d_sem out;
ret = copy_from_user(&out, post_deps++, sizeof(out)); if (copy_from_user(&out, post_deps++, sizeof(out))) {
if (ret) { ret = -EFAULT;
DRM_DEBUG("Failed to copy post dep handles\n"); DRM_DEBUG("Failed to copy post dep handles\n");
goto fail; goto fail;
} }
@ -646,9 +646,8 @@ v3d_get_multisync_submit_deps(struct drm_file *file_priv,
struct v3d_submit_ext *se = data; struct v3d_submit_ext *se = data;
int ret; int ret;
ret = copy_from_user(&multisync, ext, sizeof(multisync)); if (copy_from_user(&multisync, ext, sizeof(multisync)))
if (ret) return -EFAULT;
return ret;
if (multisync.pad) if (multisync.pad)
return -EINVAL; return -EINVAL;

Просмотреть файл

@ -308,8 +308,10 @@ virtio_gpu_user_framebuffer_create(struct drm_device *dev,
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
virtio_gpu_fb = kzalloc(sizeof(*virtio_gpu_fb), GFP_KERNEL); virtio_gpu_fb = kzalloc(sizeof(*virtio_gpu_fb), GFP_KERNEL);
if (virtio_gpu_fb == NULL) if (virtio_gpu_fb == NULL) {
drm_gem_object_put(obj);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
ret = virtio_gpu_framebuffer_init(dev, virtio_gpu_fb, mode_cmd, obj); ret = virtio_gpu_framebuffer_init(dev, virtio_gpu_fb, mode_cmd, obj);
if (ret) { if (ret) {

Просмотреть файл

@ -43,21 +43,6 @@ static void update_attr(u8 *dst, u8 *src, int attribute,
} }
} }
static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int dy, int dx, int height, int width)
{
struct fb_copyarea area;
area.sx = sx * vc->vc_font.width;
area.sy = sy * vc->vc_font.height;
area.dx = dx * vc->vc_font.width;
area.dy = dy * vc->vc_font.height;
area.height = height * vc->vc_font.height;
area.width = width * vc->vc_font.width;
info->fbops->fb_copyarea(info, &area);
}
static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int height, int width) int sx, int height, int width)
{ {
@ -393,7 +378,6 @@ static int bit_update_start(struct fb_info *info)
void fbcon_set_bitops(struct fbcon_ops *ops) void fbcon_set_bitops(struct fbcon_ops *ops)
{ {
ops->bmove = bit_bmove;
ops->clear = bit_clear; ops->clear = bit_clear;
ops->putcs = bit_putcs; ops->putcs = bit_putcs;
ops->clear_margins = bit_clear_margins; ops->clear_margins = bit_clear_margins;

Просмотреть файл

@ -173,8 +173,6 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
int count, int ypos, int xpos); int count, int ypos, int xpos);
static void fbcon_clear_margins(struct vc_data *vc, int bottom_only); static void fbcon_clear_margins(struct vc_data *vc, int bottom_only);
static void fbcon_cursor(struct vc_data *vc, int mode); static void fbcon_cursor(struct vc_data *vc, int mode);
static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
int height, int width);
static int fbcon_switch(struct vc_data *vc); static int fbcon_switch(struct vc_data *vc);
static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch); static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch);
static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table); static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table);
@ -182,16 +180,8 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table);
/* /*
* Internal routines * Internal routines
*/ */
static __inline__ void ywrap_up(struct vc_data *vc, int count);
static __inline__ void ywrap_down(struct vc_data *vc, int count);
static __inline__ void ypan_up(struct vc_data *vc, int count);
static __inline__ void ypan_down(struct vc_data *vc, int count);
static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int sx,
int dy, int dx, int height, int width, u_int y_break);
static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
int unit); int unit);
static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
int line, int count, int dy);
static void fbcon_modechanged(struct fb_info *info); static void fbcon_modechanged(struct fb_info *info);
static void fbcon_set_all_vcs(struct fb_info *info); static void fbcon_set_all_vcs(struct fb_info *info);
static void fbcon_start(void); static void fbcon_start(void);
@ -1135,14 +1125,6 @@ static void fbcon_init(struct vc_data *vc, int init)
ops->graphics = 0; ops->graphics = 0;
/*
* No more hw acceleration for fbcon.
*
* FIXME: Garbage collect all the now dead code after sufficient time
* has passed.
*/
p->scrollmode = SCROLL_REDRAW;
/* /*
* ++guenther: console.c:vc_allocate() relies on initializing * ++guenther: console.c:vc_allocate() relies on initializing
* vc_{cols,rows}, but we must not set those if we are only * vc_{cols,rows}, but we must not set those if we are only
@ -1229,14 +1211,13 @@ finished:
* This system is now divided into two levels because of complications * This system is now divided into two levels because of complications
* caused by hardware scrolling. Top level functions: * caused by hardware scrolling. Top level functions:
* *
* fbcon_bmove(), fbcon_clear(), fbcon_putc(), fbcon_clear_margins() * fbcon_clear(), fbcon_putc(), fbcon_clear_margins()
* *
* handles y values in range [0, scr_height-1] that correspond to real * handles y values in range [0, scr_height-1] that correspond to real
* screen positions. y_wrap shift means that first line of bitmap may be * screen positions. y_wrap shift means that first line of bitmap may be
* anywhere on this display. These functions convert lineoffsets to * anywhere on this display. These functions convert lineoffsets to
* bitmap offsets and deal with the wrap-around case by splitting blits. * bitmap offsets and deal with the wrap-around case by splitting blits.
* *
* fbcon_bmove_physical_8() -- These functions fast implementations
* fbcon_clear_physical_8() -- of original fbcon_XXX fns. * fbcon_clear_physical_8() -- of original fbcon_XXX fns.
* fbcon_putc_physical_8() -- (font width != 8) may be added later * fbcon_putc_physical_8() -- (font width != 8) may be added later
* *
@ -1409,224 +1390,6 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
} }
} }
static __inline__ void ywrap_up(struct vc_data *vc, int count)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
struct fbcon_display *p = &fb_display[vc->vc_num];
p->yscroll += count;
if (p->yscroll >= p->vrows) /* Deal with wrap */
p->yscroll -= p->vrows;
ops->var.xoffset = 0;
ops->var.yoffset = p->yscroll * vc->vc_font.height;
ops->var.vmode |= FB_VMODE_YWRAP;
ops->update_start(info);
scrollback_max += count;
if (scrollback_max > scrollback_phys_max)
scrollback_max = scrollback_phys_max;
scrollback_current = 0;
}
static __inline__ void ywrap_down(struct vc_data *vc, int count)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
struct fbcon_display *p = &fb_display[vc->vc_num];
p->yscroll -= count;
if (p->yscroll < 0) /* Deal with wrap */
p->yscroll += p->vrows;
ops->var.xoffset = 0;
ops->var.yoffset = p->yscroll * vc->vc_font.height;
ops->var.vmode |= FB_VMODE_YWRAP;
ops->update_start(info);
scrollback_max -= count;
if (scrollback_max < 0)
scrollback_max = 0;
scrollback_current = 0;
}
static __inline__ void ypan_up(struct vc_data *vc, int count)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_display *p = &fb_display[vc->vc_num];
struct fbcon_ops *ops = info->fbcon_par;
p->yscroll += count;
if (p->yscroll > p->vrows - vc->vc_rows) {
ops->bmove(vc, info, p->vrows - vc->vc_rows,
0, 0, 0, vc->vc_rows, vc->vc_cols);
p->yscroll -= p->vrows - vc->vc_rows;
}
ops->var.xoffset = 0;
ops->var.yoffset = p->yscroll * vc->vc_font.height;
ops->var.vmode &= ~FB_VMODE_YWRAP;
ops->update_start(info);
fbcon_clear_margins(vc, 1);
scrollback_max += count;
if (scrollback_max > scrollback_phys_max)
scrollback_max = scrollback_phys_max;
scrollback_current = 0;
}
static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
struct fbcon_display *p = &fb_display[vc->vc_num];
p->yscroll += count;
if (p->yscroll > p->vrows - vc->vc_rows) {
p->yscroll -= p->vrows - vc->vc_rows;
fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t);
}
ops->var.xoffset = 0;
ops->var.yoffset = p->yscroll * vc->vc_font.height;
ops->var.vmode &= ~FB_VMODE_YWRAP;
ops->update_start(info);
fbcon_clear_margins(vc, 1);
scrollback_max += count;
if (scrollback_max > scrollback_phys_max)
scrollback_max = scrollback_phys_max;
scrollback_current = 0;
}
static __inline__ void ypan_down(struct vc_data *vc, int count)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_display *p = &fb_display[vc->vc_num];
struct fbcon_ops *ops = info->fbcon_par;
p->yscroll -= count;
if (p->yscroll < 0) {
ops->bmove(vc, info, 0, 0, p->vrows - vc->vc_rows,
0, vc->vc_rows, vc->vc_cols);
p->yscroll += p->vrows - vc->vc_rows;
}
ops->var.xoffset = 0;
ops->var.yoffset = p->yscroll * vc->vc_font.height;
ops->var.vmode &= ~FB_VMODE_YWRAP;
ops->update_start(info);
fbcon_clear_margins(vc, 1);
scrollback_max -= count;
if (scrollback_max < 0)
scrollback_max = 0;
scrollback_current = 0;
}
static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
struct fbcon_display *p = &fb_display[vc->vc_num];
p->yscroll -= count;
if (p->yscroll < 0) {
p->yscroll += p->vrows - vc->vc_rows;
fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count);
}
ops->var.xoffset = 0;
ops->var.yoffset = p->yscroll * vc->vc_font.height;
ops->var.vmode &= ~FB_VMODE_YWRAP;
ops->update_start(info);
fbcon_clear_margins(vc, 1);
scrollback_max -= count;
if (scrollback_max < 0)
scrollback_max = 0;
scrollback_current = 0;
}
static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
int line, int count, int dy)
{
unsigned short *s = (unsigned short *)
(vc->vc_origin + vc->vc_size_row * line);
while (count--) {
unsigned short *start = s;
unsigned short *le = advance_row(s, 1);
unsigned short c;
int x = 0;
unsigned short attr = 1;
do {
c = scr_readw(s);
if (attr != (c & 0xff00)) {
attr = c & 0xff00;
if (s > start) {
fbcon_putcs(vc, start, s - start,
dy, x);
x += s - start;
start = s;
}
}
console_conditional_schedule();
s++;
} while (s < le);
if (s > start)
fbcon_putcs(vc, start, s - start, dy, x);
console_conditional_schedule();
dy++;
}
}
static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info,
struct fbcon_display *p, int line, int count, int ycount)
{
int offset = ycount * vc->vc_cols;
unsigned short *d = (unsigned short *)
(vc->vc_origin + vc->vc_size_row * line);
unsigned short *s = d + offset;
struct fbcon_ops *ops = info->fbcon_par;
while (count--) {
unsigned short *start = s;
unsigned short *le = advance_row(s, 1);
unsigned short c;
int x = 0;
do {
c = scr_readw(s);
if (c == scr_readw(d)) {
if (s > start) {
ops->bmove(vc, info, line + ycount, x,
line, x, 1, s-start);
x += s - start + 1;
start = s + 1;
} else {
x++;
start++;
}
}
scr_writew(c, d);
console_conditional_schedule();
s++;
d++;
} while (s < le);
if (s > start)
ops->bmove(vc, info, line + ycount, x, line, x, 1,
s-start);
console_conditional_schedule();
if (ycount > 0)
line++;
else {
line--;
/* NOTE: We subtract two lines from these pointers */
s -= vc->vc_size_row;
d -= vc->vc_size_row;
}
}
}
static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p, static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p,
int line, int count, int offset) int line, int count, int offset)
{ {
@ -1687,7 +1450,6 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
{ {
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_display *p = &fb_display[vc->vc_num]; struct fbcon_display *p = &fb_display[vc->vc_num];
int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
if (fbcon_is_inactive(vc, info)) if (fbcon_is_inactive(vc, info))
return true; return true;
@ -1704,249 +1466,32 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
case SM_UP: case SM_UP:
if (count > vc->vc_rows) /* Maximum realistic size */ if (count > vc->vc_rows) /* Maximum realistic size */
count = vc->vc_rows; count = vc->vc_rows;
if (logo_shown >= 0) fbcon_redraw(vc, p, t, b - t - count,
goto redraw_up; count * vc->vc_cols);
switch (p->scrollmode) { fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
case SCROLL_MOVE: scr_memsetw((unsigned short *) (vc->vc_origin +
fbcon_redraw_blit(vc, info, p, t, b - t - count, vc->vc_size_row *
count); (b - count)),
fbcon_clear(vc, b - count, 0, count, vc->vc_cols); vc->vc_video_erase_char,
scr_memsetw((unsigned short *) (vc->vc_origin + vc->vc_size_row * count);
vc->vc_size_row * return true;
(b - count)),
vc->vc_video_erase_char,
vc->vc_size_row * count);
return true;
case SCROLL_WRAP_MOVE:
if (b - t - count > 3 * vc->vc_rows >> 2) {
if (t > 0)
fbcon_bmove(vc, 0, 0, count, 0, t,
vc->vc_cols);
ywrap_up(vc, count);
if (vc->vc_rows - b > 0)
fbcon_bmove(vc, b - count, 0, b, 0,
vc->vc_rows - b,
vc->vc_cols);
} else if (info->flags & FBINFO_READS_FAST)
fbcon_bmove(vc, t + count, 0, t, 0,
b - t - count, vc->vc_cols);
else
goto redraw_up;
fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
break;
case SCROLL_PAN_REDRAW:
if ((p->yscroll + count <=
2 * (p->vrows - vc->vc_rows))
&& ((!scroll_partial && (b - t == vc->vc_rows))
|| (scroll_partial
&& (b - t - count >
3 * vc->vc_rows >> 2)))) {
if (t > 0)
fbcon_redraw_move(vc, p, 0, t, count);
ypan_up_redraw(vc, t, count);
if (vc->vc_rows - b > 0)
fbcon_redraw_move(vc, p, b,
vc->vc_rows - b, b);
} else
fbcon_redraw_move(vc, p, t + count, b - t - count, t);
fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
break;
case SCROLL_PAN_MOVE:
if ((p->yscroll + count <=
2 * (p->vrows - vc->vc_rows))
&& ((!scroll_partial && (b - t == vc->vc_rows))
|| (scroll_partial
&& (b - t - count >
3 * vc->vc_rows >> 2)))) {
if (t > 0)
fbcon_bmove(vc, 0, 0, count, 0, t,
vc->vc_cols);
ypan_up(vc, count);
if (vc->vc_rows - b > 0)
fbcon_bmove(vc, b - count, 0, b, 0,
vc->vc_rows - b,
vc->vc_cols);
} else if (info->flags & FBINFO_READS_FAST)
fbcon_bmove(vc, t + count, 0, t, 0,
b - t - count, vc->vc_cols);
else
goto redraw_up;
fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
break;
case SCROLL_REDRAW:
redraw_up:
fbcon_redraw(vc, p, t, b - t - count,
count * vc->vc_cols);
fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row *
(b - count)),
vc->vc_video_erase_char,
vc->vc_size_row * count);
return true;
}
break;
case SM_DOWN: case SM_DOWN:
if (count > vc->vc_rows) /* Maximum realistic size */ if (count > vc->vc_rows) /* Maximum realistic size */
count = vc->vc_rows; count = vc->vc_rows;
if (logo_shown >= 0) fbcon_redraw(vc, p, b - 1, b - t - count,
goto redraw_down; -count * vc->vc_cols);
switch (p->scrollmode) { fbcon_clear(vc, t, 0, count, vc->vc_cols);
case SCROLL_MOVE: scr_memsetw((unsigned short *) (vc->vc_origin +
fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, vc->vc_size_row *
-count); t),
fbcon_clear(vc, t, 0, count, vc->vc_cols); vc->vc_video_erase_char,
scr_memsetw((unsigned short *) (vc->vc_origin + vc->vc_size_row * count);
vc->vc_size_row * return true;
t),
vc->vc_video_erase_char,
vc->vc_size_row * count);
return true;
case SCROLL_WRAP_MOVE:
if (b - t - count > 3 * vc->vc_rows >> 2) {
if (vc->vc_rows - b > 0)
fbcon_bmove(vc, b, 0, b - count, 0,
vc->vc_rows - b,
vc->vc_cols);
ywrap_down(vc, count);
if (t > 0)
fbcon_bmove(vc, count, 0, 0, 0, t,
vc->vc_cols);
} else if (info->flags & FBINFO_READS_FAST)
fbcon_bmove(vc, t, 0, t + count, 0,
b - t - count, vc->vc_cols);
else
goto redraw_down;
fbcon_clear(vc, t, 0, count, vc->vc_cols);
break;
case SCROLL_PAN_MOVE:
if ((count - p->yscroll <= p->vrows - vc->vc_rows)
&& ((!scroll_partial && (b - t == vc->vc_rows))
|| (scroll_partial
&& (b - t - count >
3 * vc->vc_rows >> 2)))) {
if (vc->vc_rows - b > 0)
fbcon_bmove(vc, b, 0, b - count, 0,
vc->vc_rows - b,
vc->vc_cols);
ypan_down(vc, count);
if (t > 0)
fbcon_bmove(vc, count, 0, 0, 0, t,
vc->vc_cols);
} else if (info->flags & FBINFO_READS_FAST)
fbcon_bmove(vc, t, 0, t + count, 0,
b - t - count, vc->vc_cols);
else
goto redraw_down;
fbcon_clear(vc, t, 0, count, vc->vc_cols);
break;
case SCROLL_PAN_REDRAW:
if ((count - p->yscroll <= p->vrows - vc->vc_rows)
&& ((!scroll_partial && (b - t == vc->vc_rows))
|| (scroll_partial
&& (b - t - count >
3 * vc->vc_rows >> 2)))) {
if (vc->vc_rows - b > 0)
fbcon_redraw_move(vc, p, b, vc->vc_rows - b,
b - count);
ypan_down_redraw(vc, t, count);
if (t > 0)
fbcon_redraw_move(vc, p, count, t, 0);
} else
fbcon_redraw_move(vc, p, t, b - t - count, t + count);
fbcon_clear(vc, t, 0, count, vc->vc_cols);
break;
case SCROLL_REDRAW:
redraw_down:
fbcon_redraw(vc, p, b - 1, b - t - count,
-count * vc->vc_cols);
fbcon_clear(vc, t, 0, count, vc->vc_cols);
scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row *
t),
vc->vc_video_erase_char,
vc->vc_size_row * count);
return true;
}
} }
return false; return false;
} }
static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
int height, int width)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_display *p = &fb_display[vc->vc_num];
if (fbcon_is_inactive(vc, info))
return;
if (!width || !height)
return;
/* Split blits that cross physical y_wrap case.
* Pathological case involves 4 blits, better to use recursive
* code rather than unrolled case
*
* Recursive invocations don't need to erase the cursor over and
* over again, so we use fbcon_bmove_rec()
*/
fbcon_bmove_rec(vc, p, sy, sx, dy, dx, height, width,
p->vrows - p->yscroll);
}
static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int sx,
int dy, int dx, int height, int width, u_int y_break)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
u_int b;
if (sy < y_break && sy + height > y_break) {
b = y_break - sy;
if (dy < sy) { /* Avoid trashing self */
fbcon_bmove_rec(vc, p, sy, sx, dy, dx, b, width,
y_break);
fbcon_bmove_rec(vc, p, sy + b, sx, dy + b, dx,
height - b, width, y_break);
} else {
fbcon_bmove_rec(vc, p, sy + b, sx, dy + b, dx,
height - b, width, y_break);
fbcon_bmove_rec(vc, p, sy, sx, dy, dx, b, width,
y_break);
}
return;
}
if (dy < y_break && dy + height > y_break) {
b = y_break - dy;
if (dy < sy) { /* Avoid trashing self */
fbcon_bmove_rec(vc, p, sy, sx, dy, dx, b, width,
y_break);
fbcon_bmove_rec(vc, p, sy + b, sx, dy + b, dx,
height - b, width, y_break);
} else {
fbcon_bmove_rec(vc, p, sy + b, sx, dy + b, dx,
height - b, width, y_break);
fbcon_bmove_rec(vc, p, sy, sx, dy, dx, b, width,
y_break);
}
return;
}
ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx,
height, width);
}
static void updatescrollmode(struct fbcon_display *p, static void updatescrollmode(struct fbcon_display *p,
struct fb_info *info, struct fb_info *info,
struct vc_data *vc) struct vc_data *vc)
@ -2119,21 +1664,7 @@ static int fbcon_switch(struct vc_data *vc)
updatescrollmode(p, info, vc); updatescrollmode(p, info, vc);
switch (p->scrollmode) { scrollback_phys_max = 0;
case SCROLL_WRAP_MOVE:
scrollback_phys_max = p->vrows - vc->vc_rows;
break;
case SCROLL_PAN_MOVE:
case SCROLL_PAN_REDRAW:
scrollback_phys_max = p->vrows - 2 * vc->vc_rows;
if (scrollback_phys_max < 0)
scrollback_phys_max = 0;
break;
default:
scrollback_phys_max = 0;
break;
}
scrollback_max = 0; scrollback_max = 0;
scrollback_current = 0; scrollback_current = 0;

Просмотреть файл

@ -29,7 +29,6 @@ struct fbcon_display {
/* Filled in by the low-level console driver */ /* Filled in by the low-level console driver */
const u_char *fontdata; const u_char *fontdata;
int userfont; /* != 0 if fontdata kmalloc()ed */ int userfont; /* != 0 if fontdata kmalloc()ed */
u_short scrollmode; /* Scroll Method */
u_short inverse; /* != 0 text black on white as default */ u_short inverse; /* != 0 text black on white as default */
short yscroll; /* Hardware scrolling */ short yscroll; /* Hardware scrolling */
int vrows; /* number of virtual rows */ int vrows; /* number of virtual rows */
@ -52,8 +51,6 @@ struct fbcon_display {
}; };
struct fbcon_ops { struct fbcon_ops {
void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int dy, int dx, int height, int width);
void (*clear)(struct vc_data *vc, struct fb_info *info, int sy, void (*clear)(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int height, int width); int sx, int height, int width);
void (*putcs)(struct vc_data *vc, struct fb_info *info, void (*putcs)(struct vc_data *vc, struct fb_info *info,
@ -152,62 +149,6 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
#define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0) #define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0)
#define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1) #define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1)
/*
* Scroll Method
*/
/* There are several methods fbcon can use to move text around the screen:
*
* Operation Pan Wrap
*---------------------------------------------
* SCROLL_MOVE copyarea No No
* SCROLL_PAN_MOVE copyarea Yes No
* SCROLL_WRAP_MOVE copyarea No Yes
* SCROLL_REDRAW imageblit No No
* SCROLL_PAN_REDRAW imageblit Yes No
* SCROLL_WRAP_REDRAW imageblit No Yes
*
* (SCROLL_WRAP_REDRAW is not implemented yet)
*
* In general, fbcon will choose the best scrolling
* method based on the rule below:
*
* Pan/Wrap > accel imageblit > accel copyarea >
* soft imageblit > (soft copyarea)
*
* Exception to the rule: Pan + accel copyarea is
* preferred over Pan + accel imageblit.
*
* The above is typical for PCI/AGP cards. Unless
* overridden, fbcon will never use soft copyarea.
*
* If you need to override the above rule, set the
* appropriate flags in fb_info->flags. For example,
* to prefer copyarea over imageblit, set
* FBINFO_READS_FAST.
*
* Other notes:
* + use the hardware engine to move the text
* (hw-accelerated copyarea() and fillrect())
* + use hardware-supported panning on a large virtual screen
* + amifb can not only pan, but also wrap the display by N lines
* (i.e. visible line i = physical line (i+N) % yres).
* + read what's already rendered on the screen and
* write it in a different place (this is cfb_copyarea())
* + re-render the text to the screen
*
* Whether to use wrapping or panning can only be figured out at
* runtime (when we know whether our font height is a multiple
* of the pan/wrap step)
*
*/
#define SCROLL_MOVE 0x001
#define SCROLL_PAN_MOVE 0x002
#define SCROLL_WRAP_MOVE 0x003
#define SCROLL_REDRAW 0x004
#define SCROLL_PAN_REDRAW 0x005
#ifdef CONFIG_FB_TILEBLITTING #ifdef CONFIG_FB_TILEBLITTING
extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info); extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
#endif #endif

Просмотреть файл

@ -59,31 +59,12 @@ static void ccw_update_attr(u8 *dst, u8 *src, int attribute,
} }
} }
static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int dy, int dx, int height, int width)
{
struct fbcon_ops *ops = info->fbcon_par;
struct fb_copyarea area;
u32 vyres = GETVYRES(ops->p->scrollmode, info);
area.sx = sy * vc->vc_font.height;
area.sy = vyres - ((sx + width) * vc->vc_font.width);
area.dx = dy * vc->vc_font.height;
area.dy = vyres - ((dx + width) * vc->vc_font.width);
area.width = height * vc->vc_font.height;
area.height = width * vc->vc_font.width;
info->fbops->fb_copyarea(info, &area);
}
static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int height, int width) int sx, int height, int width)
{ {
struct fbcon_ops *ops = info->fbcon_par;
struct fb_fillrect region; struct fb_fillrect region;
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = info->var.yres;
region.color = attr_bgcol_ec(bgshift,vc,info); region.color = attr_bgcol_ec(bgshift,vc,info);
region.dx = sy * vc->vc_font.height; region.dx = sy * vc->vc_font.height;
@ -140,7 +121,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info,
u32 cnt, pitch, size; u32 cnt, pitch, size;
u32 attribute = get_attribute(info, scr_readw(s)); u32 attribute = get_attribute(info, scr_readw(s));
u8 *dst, *buf = NULL; u8 *dst, *buf = NULL;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = info->var.yres;
if (!ops->fontbuffer) if (!ops->fontbuffer)
return; return;
@ -229,7 +210,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy; int err = 1, dx, dy;
char *src; char *src;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = info->var.yres;
if (!ops->fontbuffer) if (!ops->fontbuffer)
return; return;
@ -387,7 +368,7 @@ static int ccw_update_start(struct fb_info *info)
{ {
struct fbcon_ops *ops = info->fbcon_par; struct fbcon_ops *ops = info->fbcon_par;
u32 yoffset; u32 yoffset;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = info->var.yres;
int err; int err;
yoffset = (vyres - info->var.yres) - ops->var.xoffset; yoffset = (vyres - info->var.yres) - ops->var.xoffset;
@ -402,7 +383,6 @@ static int ccw_update_start(struct fb_info *info)
void fbcon_rotate_ccw(struct fbcon_ops *ops) void fbcon_rotate_ccw(struct fbcon_ops *ops)
{ {
ops->bmove = ccw_bmove;
ops->clear = ccw_clear; ops->clear = ccw_clear;
ops->putcs = ccw_putcs; ops->putcs = ccw_putcs;
ops->clear_margins = ccw_clear_margins; ops->clear_margins = ccw_clear_margins;

Просмотреть файл

@ -44,31 +44,12 @@ static void cw_update_attr(u8 *dst, u8 *src, int attribute,
} }
} }
static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int dy, int dx, int height, int width)
{
struct fbcon_ops *ops = info->fbcon_par;
struct fb_copyarea area;
u32 vxres = GETVXRES(ops->p->scrollmode, info);
area.sx = vxres - ((sy + height) * vc->vc_font.height);
area.sy = sx * vc->vc_font.width;
area.dx = vxres - ((dy + height) * vc->vc_font.height);
area.dy = dx * vc->vc_font.width;
area.width = height * vc->vc_font.height;
area.height = width * vc->vc_font.width;
info->fbops->fb_copyarea(info, &area);
}
static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int height, int width) int sx, int height, int width)
{ {
struct fbcon_ops *ops = info->fbcon_par;
struct fb_fillrect region; struct fb_fillrect region;
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = info->var.xres;
region.color = attr_bgcol_ec(bgshift,vc,info); region.color = attr_bgcol_ec(bgshift,vc,info);
region.dx = vxres - ((sy + height) * vc->vc_font.height); region.dx = vxres - ((sy + height) * vc->vc_font.height);
@ -125,7 +106,7 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info,
u32 cnt, pitch, size; u32 cnt, pitch, size;
u32 attribute = get_attribute(info, scr_readw(s)); u32 attribute = get_attribute(info, scr_readw(s));
u8 *dst, *buf = NULL; u8 *dst, *buf = NULL;
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = info->var.xres;
if (!ops->fontbuffer) if (!ops->fontbuffer)
return; return;
@ -212,7 +193,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy; int err = 1, dx, dy;
char *src; char *src;
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = info->var.xres;
if (!ops->fontbuffer) if (!ops->fontbuffer)
return; return;
@ -369,7 +350,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
static int cw_update_start(struct fb_info *info) static int cw_update_start(struct fb_info *info)
{ {
struct fbcon_ops *ops = info->fbcon_par; struct fbcon_ops *ops = info->fbcon_par;
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = info->var.xres;
u32 xoffset; u32 xoffset;
int err; int err;
@ -385,7 +366,6 @@ static int cw_update_start(struct fb_info *info)
void fbcon_rotate_cw(struct fbcon_ops *ops) void fbcon_rotate_cw(struct fbcon_ops *ops)
{ {
ops->bmove = cw_bmove;
ops->clear = cw_clear; ops->clear = cw_clear;
ops->putcs = cw_putcs; ops->putcs = cw_putcs;
ops->clear_margins = cw_clear_margins; ops->clear_margins = cw_clear_margins;

Просмотреть файл

@ -11,15 +11,6 @@
#ifndef _FBCON_ROTATE_H #ifndef _FBCON_ROTATE_H
#define _FBCON_ROTATE_H #define _FBCON_ROTATE_H
#define GETVYRES(s,i) ({ \
(s == SCROLL_REDRAW || s == SCROLL_MOVE) ? \
(i)->var.yres : (i)->var.yres_virtual; })
#define GETVXRES(s,i) ({ \
(s == SCROLL_REDRAW || s == SCROLL_MOVE || !(i)->fix.xpanstep) ? \
(i)->var.xres : (i)->var.xres_virtual; })
static inline int pattern_test_bit(u32 x, u32 y, u32 pitch, const char *pat) static inline int pattern_test_bit(u32 x, u32 y, u32 pitch, const char *pat)
{ {
u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8; u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8;

Просмотреть файл

@ -44,33 +44,13 @@ static void ud_update_attr(u8 *dst, u8 *src, int attribute,
} }
} }
static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int dy, int dx, int height, int width)
{
struct fbcon_ops *ops = info->fbcon_par;
struct fb_copyarea area;
u32 vyres = GETVYRES(ops->p->scrollmode, info);
u32 vxres = GETVXRES(ops->p->scrollmode, info);
area.sy = vyres - ((sy + height) * vc->vc_font.height);
area.sx = vxres - ((sx + width) * vc->vc_font.width);
area.dy = vyres - ((dy + height) * vc->vc_font.height);
area.dx = vxres - ((dx + width) * vc->vc_font.width);
area.height = height * vc->vc_font.height;
area.width = width * vc->vc_font.width;
info->fbops->fb_copyarea(info, &area);
}
static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int height, int width) int sx, int height, int width)
{ {
struct fbcon_ops *ops = info->fbcon_par;
struct fb_fillrect region; struct fb_fillrect region;
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = info->var.yres;
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = info->var.xres;
region.color = attr_bgcol_ec(bgshift,vc,info); region.color = attr_bgcol_ec(bgshift,vc,info);
region.dy = vyres - ((sy + height) * vc->vc_font.height); region.dy = vyres - ((sy + height) * vc->vc_font.height);
@ -162,8 +142,8 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info,
u32 mod = vc->vc_font.width % 8, cnt, pitch, size; u32 mod = vc->vc_font.width % 8, cnt, pitch, size;
u32 attribute = get_attribute(info, scr_readw(s)); u32 attribute = get_attribute(info, scr_readw(s));
u8 *dst, *buf = NULL; u8 *dst, *buf = NULL;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = info->var.yres;
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = info->var.xres;
if (!ops->fontbuffer) if (!ops->fontbuffer)
return; return;
@ -259,8 +239,8 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy; int err = 1, dx, dy;
char *src; char *src;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = info->var.yres;
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = info->var.xres;
if (!ops->fontbuffer) if (!ops->fontbuffer)
return; return;
@ -410,8 +390,8 @@ static int ud_update_start(struct fb_info *info)
{ {
struct fbcon_ops *ops = info->fbcon_par; struct fbcon_ops *ops = info->fbcon_par;
int xoffset, yoffset; int xoffset, yoffset;
u32 vyres = GETVYRES(ops->p->scrollmode, info); u32 vyres = info->var.yres;
u32 vxres = GETVXRES(ops->p->scrollmode, info); u32 vxres = info->var.xres;
int err; int err;
xoffset = vxres - info->var.xres - ops->var.xoffset; xoffset = vxres - info->var.xres - ops->var.xoffset;
@ -429,7 +409,6 @@ static int ud_update_start(struct fb_info *info)
void fbcon_rotate_ud(struct fbcon_ops *ops) void fbcon_rotate_ud(struct fbcon_ops *ops)
{ {
ops->bmove = ud_bmove;
ops->clear = ud_clear; ops->clear = ud_clear;
ops->putcs = ud_putcs; ops->putcs = ud_putcs;
ops->clear_margins = ud_clear_margins; ops->clear_margins = ud_clear_margins;

Просмотреть файл

@ -1702,8 +1702,11 @@ static void do_unregister_framebuffer(struct fb_info *fb_info)
{ {
unlink_framebuffer(fb_info); unlink_framebuffer(fb_info);
if (fb_info->pixmap.addr && if (fb_info->pixmap.addr &&
(fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) {
kfree(fb_info->pixmap.addr); kfree(fb_info->pixmap.addr);
fb_info->pixmap.addr = NULL;
}
fb_destroy_modelist(&fb_info->modelist); fb_destroy_modelist(&fb_info->modelist);
registered_fb[fb_info->node] = NULL; registered_fb[fb_info->node] = NULL;
num_registered_fb--; num_registered_fb--;

Просмотреть файл

@ -16,21 +16,6 @@
#include <asm/types.h> #include <asm/types.h>
#include "fbcon.h" #include "fbcon.h"
static void tile_bmove(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int dy, int dx, int height, int width)
{
struct fb_tilearea area;
area.sx = sx;
area.sy = sy;
area.dx = dx;
area.dy = dy;
area.height = height;
area.width = width;
info->tileops->fb_tilecopy(info, &area);
}
static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy, static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int height, int width) int sx, int height, int width)
{ {
@ -133,7 +118,6 @@ void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info)
struct fb_tilemap map; struct fb_tilemap map;
struct fbcon_ops *ops = info->fbcon_par; struct fbcon_ops *ops = info->fbcon_par;
ops->bmove = tile_bmove;
ops->clear = tile_clear; ops->clear = tile_clear;
ops->putcs = tile_putcs; ops->putcs = tile_putcs;
ops->clear_margins = tile_clear_margins; ops->clear_margins = tile_clear_margins;

Просмотреть файл

@ -505,15 +505,15 @@ void xxxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region)
} }
/** /**
* xxxfb_copyarea - REQUIRED function. Can use generic routines if * xxxfb_copyarea - OBSOLETE function.
* non acclerated hardware and packed pixel based.
* Copies one area of the screen to another area. * Copies one area of the screen to another area.
* Will be deleted in a future version
* *
* @info: frame buffer structure that represents a single frame buffer * @info: frame buffer structure that represents a single frame buffer
* @area: Structure providing the data to copy the framebuffer contents * @area: Structure providing the data to copy the framebuffer contents
* from one region to another. * from one region to another.
* *
* This drawing operation copies a rectangular area from one area of the * This drawing operation copied a rectangular area from one area of the
* screen to another area. * screen to another area.
*/ */
void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
@ -645,9 +645,9 @@ static const struct fb_ops xxxfb_ops = {
.fb_setcolreg = xxxfb_setcolreg, .fb_setcolreg = xxxfb_setcolreg,
.fb_blank = xxxfb_blank, .fb_blank = xxxfb_blank,
.fb_pan_display = xxxfb_pan_display, .fb_pan_display = xxxfb_pan_display,
.fb_fillrect = xxxfb_fillrect, /* Needed !!! */ .fb_fillrect = xxxfb_fillrect, /* Needed !!! */
.fb_copyarea = xxxfb_copyarea, /* Needed !!! */ .fb_copyarea = xxxfb_copyarea, /* Obsolete */
.fb_imageblit = xxxfb_imageblit, /* Needed !!! */ .fb_imageblit = xxxfb_imageblit, /* Needed !!! */
.fb_cursor = xxxfb_cursor, /* Optional !!! */ .fb_cursor = xxxfb_cursor, /* Optional !!! */
.fb_sync = xxxfb_sync, .fb_sync = xxxfb_sync,
.fb_ioctl = xxxfb_ioctl, .fb_ioctl = xxxfb_ioctl,

Просмотреть файл

@ -24,6 +24,8 @@
#ifndef DRM_MODESET_LOCK_H_ #ifndef DRM_MODESET_LOCK_H_
#define DRM_MODESET_LOCK_H_ #define DRM_MODESET_LOCK_H_
#include <linux/types.h> /* stackdepot.h is not self-contained */
#include <linux/stackdepot.h>
#include <linux/ww_mutex.h> #include <linux/ww_mutex.h>
struct drm_modeset_lock; struct drm_modeset_lock;
@ -51,6 +53,12 @@ struct drm_modeset_acquire_ctx {
*/ */
struct drm_modeset_lock *contended; struct drm_modeset_lock *contended;
/*
* Stack depot for debugging when a contended lock was not backed off
* from.
*/
depot_stack_handle_t stack_depot;
/* /*
* list of held locks (drm_modeset_lock) * list of held locks (drm_modeset_lock)
*/ */

Просмотреть файл

@ -351,9 +351,10 @@ bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
* @bo: Pointer to a ttm_buffer_object to be initialized. * @bo: Pointer to a ttm_buffer_object to be initialized.
* @size: Requested size of buffer object. * @size: Requested size of buffer object.
* @type: Requested type of buffer object. * @type: Requested type of buffer object.
* @flags: Initial placement flags. * @placement: Initial placement for buffer object.
* @page_alignment: Data alignment in pages. * @page_alignment: Data alignment in pages.
* @ctx: TTM operation context for memory allocation. * @ctx: TTM operation context for memory allocation.
* @sg: Scatter-gather table.
* @resv: Pointer to a dma_resv, or NULL to let ttm allocate one. * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one.
* @destroy: Destroy function. Use NULL for kfree(). * @destroy: Destroy function. Use NULL for kfree().
* *
@ -394,7 +395,7 @@ int ttm_bo_init_reserved(struct ttm_device *bdev,
* @bo: Pointer to a ttm_buffer_object to be initialized. * @bo: Pointer to a ttm_buffer_object to be initialized.
* @size: Requested size of buffer object. * @size: Requested size of buffer object.
* @type: Requested type of buffer object. * @type: Requested type of buffer object.
* @flags: Initial placement flags. * @placement: Initial placement for buffer object.
* @page_alignment: Data alignment in pages. * @page_alignment: Data alignment in pages.
* @interruptible: If needing to sleep to wait for GPU resources, * @interruptible: If needing to sleep to wait for GPU resources,
* sleep interruptible. * sleep interruptible.
@ -402,6 +403,7 @@ int ttm_bo_init_reserved(struct ttm_device *bdev,
* holds a pointer to a persistent shmem object. Typically, this would * holds a pointer to a persistent shmem object. Typically, this would
* point to the shmem object backing a GEM object if TTM is used to back a * point to the shmem object backing a GEM object if TTM is used to back a
* GEM user interface. * GEM user interface.
* @sg: Scatter-gather table.
* @resv: Pointer to a dma_resv, or NULL to let ttm allocate one. * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one.
* @destroy: Destroy function. Use NULL for kfree(). * @destroy: Destroy function. Use NULL for kfree().
* *

Просмотреть файл

@ -170,15 +170,20 @@ struct dma_resv_iter {
/** @index: index into the shared fences */ /** @index: index into the shared fences */
unsigned int index; unsigned int index;
/** @fences: the shared fences */ /** @fences: the shared fences; private, *MUST* not dereference */
struct dma_resv_list *fences; struct dma_resv_list *fences;
/** @shared_count: number of shared fences */
unsigned int shared_count;
/** @is_restarted: true if this is the first returned fence */ /** @is_restarted: true if this is the first returned fence */
bool is_restarted; bool is_restarted;
}; };
struct dma_fence *dma_resv_iter_first_unlocked(struct dma_resv_iter *cursor); struct dma_fence *dma_resv_iter_first_unlocked(struct dma_resv_iter *cursor);
struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor); struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor);
struct dma_fence *dma_resv_iter_first(struct dma_resv_iter *cursor);
struct dma_fence *dma_resv_iter_next(struct dma_resv_iter *cursor);
/** /**
* dma_resv_iter_begin - initialize a dma_resv_iter object * dma_resv_iter_begin - initialize a dma_resv_iter object
@ -244,6 +249,24 @@ static inline bool dma_resv_iter_is_restarted(struct dma_resv_iter *cursor)
for (fence = dma_resv_iter_first_unlocked(cursor); \ for (fence = dma_resv_iter_first_unlocked(cursor); \
fence; fence = dma_resv_iter_next_unlocked(cursor)) fence; fence = dma_resv_iter_next_unlocked(cursor))
/**
* dma_resv_for_each_fence - fence iterator
* @cursor: a struct dma_resv_iter pointer
* @obj: a dma_resv object pointer
* @all_fences: true if all fences should be returned
* @fence: the current fence
*
* Iterate over the fences in a struct dma_resv object while holding the
* &dma_resv.lock. @all_fences controls if the shared fences are returned as
* well. The cursor initialisation is part of the iterator and the fence stays
* valid as long as the lock is held and so no extra reference to the fence is
* taken.
*/
#define dma_resv_for_each_fence(cursor, obj, all_fences, fence) \
for (dma_resv_iter_begin(cursor, obj, all_fences), \
fence = dma_resv_iter_first(cursor); fence; \
fence = dma_resv_iter_next(cursor))
#define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base) #define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base)
#define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base) #define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base)

Просмотреть файл

@ -262,7 +262,7 @@ struct fb_ops {
/* Draws a rectangle */ /* Draws a rectangle */
void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect); void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
/* Copy data from area to another */ /* Copy data from area to another. Obsolete. */
void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region); void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
/* Draws a image to the display */ /* Draws a image to the display */
void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image); void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);