drm-misc-next for 5.11:
UAPI Changes: * media: Add MEDIA_BUS_FMT_RGB888_3X8_DELTA format Cross-subsystem Changes: * console: Remove unused functions; Store characters-per-font in font- descriptor structure instead of hard-coding * DT: Add vendor prefix for ShenZhen Asia Better Technology Ltd. (ABT) Core Changes: * Fix build warnings * Update debug logging to new interfaces, plus fixes * Add error messages for ioctls; * Fix kernel docs * doc: Fix kernel docs * fbcon: Remove accelerated scrolling * selftests: Fix build warnings * ttm: Fix missing NULL check in new page pool; Fix build warnings * video: Fix kernel docs Driver Changes: * armada: Fix build warnings * atmel-hlcdc: Fix build warnings * exynos: Fix build warnings * gma500: Remove 2d framebuffer acceleration * lima: Fix build warnings; Cleanups * mediatek: Fix build warnings * meson: Module removal fixes; Fix build warnings * nouveau: Fix build warnings * omap: Fix return values * panel: Fix build warnings; Add support and DT bindings for OnePlus 6/T; Add support and DT bindings for ABT Y030XX067A * panel/s6e63m0: Add/improve SPi reading/writing; Support 3WIRE protocol; Set connector display info; Add more comments * panfrost: Move GPU reset into separate worker, avoid race conditions * pl111: Fix build warnings * qxl: Cleanup fbcon acceleration * rockchip: Fix build warnings * savage: Fix build warnings * sti: Fix build warnings * udl: Fix missing error code in udl_handle_damage() * v3d: Fix build warnings * vc4: Fix build warnings * via: Fix build warnings * virtio: Make dma-buf ops static -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEchf7rIzpz2NEoWjlaA3BHVMLeiMFAl+1E5wACgkQaA3BHVML eiOu3Af6A/s2V2g0ekPtEit/s0w4o8Yp1drZhTe5//PHXwcEl8tpeCmm6stCRtW+ LT1HeivmU4cxHygWZkaLeBpSX7ncqTbq2iRks250NmfjWRLyZVUIiNcfveiPo/eX n7S3YapsZqUQ0bTIg2F3utqW5qPhzIVbpORQwIiDzhGqI0npgwhXB9iEVuB5KnvJ by54OiGyEJf6M5ojalSkFE4YPldfRgVhfL73Kyfw/SO7VOvf5xxcZp/ezMUUOGTM gsxmn0DpKwRKM546Fi2MJ3jamGoZDKx6IwYx37Vz9nlLi4Qt0XVg1kXo8fHX6Ycw uzgxPetu5DmxaVSYTb6iD4D1axDbQg== =EcDc -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2020-11-18' of ssh://git.freedesktop.org/git/drm/drm-misc into drm-next drm-misc-next for 5.11: UAPI Changes: * media: Add MEDIA_BUS_FMT_RGB888_3X8_DELTA format Cross-subsystem Changes: * console: Remove unused functions; Store characters-per-font in font- descriptor structure instead of hard-coding * DT: Add vendor prefix for ShenZhen Asia Better Technology Ltd. (ABT) Core Changes: * Fix build warnings * Update debug logging to new interfaces, plus fixes * Add error messages for ioctls; * Fix kernel docs * doc: Fix kernel docs * fbcon: Remove accelerated scrolling * selftests: Fix build warnings * ttm: Fix missing NULL check in new page pool; Fix build warnings * video: Fix kernel docs Driver Changes: * armada: Fix build warnings * atmel-hlcdc: Fix build warnings * exynos: Fix build warnings * gma500: Remove 2d framebuffer acceleration * lima: Fix build warnings; Cleanups * mediatek: Fix build warnings * meson: Module removal fixes; Fix build warnings * nouveau: Fix build warnings * omap: Fix return values * panel: Fix build warnings; Add support and DT bindings for OnePlus 6/T; Add support and DT bindings for ABT Y030XX067A * panel/s6e63m0: Add/improve SPi reading/writing; Support 3WIRE protocol; Set connector display info; Add more comments * panfrost: Move GPU reset into separate worker, avoid race conditions * pl111: Fix build warnings * qxl: Cleanup fbcon acceleration * rockchip: Fix build warnings * savage: Fix build warnings * sti: Fix build warnings * udl: Fix missing error code in udl_handle_damage() * v3d: Fix build warnings * vc4: Fix build warnings * via: Fix build warnings * virtio: Make dma-buf ops static Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20201118123221.GA19755@linux-uq9g
This commit is contained in:
commit
22f8c80566
@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/abt,y030xx067a.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Asia Better Technology 3.0" (320x480 pixels) 24-bit IPS LCD panel
|
||||
|
||||
description: |
|
||||
The panel must obey the rules for a SPI slave device as specified in
|
||||
spi/spi-controller.yaml
|
||||
|
||||
maintainers:
|
||||
- Paul Cercueil <paul@crapouillou.net>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: abt,y030xx067a
|
||||
|
||||
backlight: true
|
||||
port: true
|
||||
power-supply: true
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- power-supply
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "abt,y030xx067a";
|
||||
reg = <0>;
|
||||
|
||||
spi-max-frequency = <3125000>;
|
||||
|
||||
reset-gpios = <&gpe 2 GPIO_ACTIVE_LOW>;
|
||||
|
||||
backlight = <&backlight>;
|
||||
power-supply = <&vcc>;
|
||||
|
||||
port {
|
||||
panel_input: endpoint {
|
||||
remote-endpoint = <&panel_output>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -47,6 +47,10 @@ properties:
|
||||
- panasonic,vvx10f004b00
|
||||
# Panasonic 10" WUXGA TFT LCD panel
|
||||
- panasonic,vvx10f034n00
|
||||
# Samsung s6e3fc2x01 1080x2340 AMOLED panel
|
||||
- samsung,s6e3fc2x01
|
||||
# Samsung sofef00 1080x2280 AMOLED panel
|
||||
- samsung,sofef00
|
||||
# Shangai Top Display Optoelectronics 7" TL070WSH30 1024x600 TFT LCD panel
|
||||
- tdo,tl070wsh30
|
||||
|
||||
|
@ -29,6 +29,8 @@ patternProperties:
|
||||
description: Abilis Systems
|
||||
"^abracon,.*":
|
||||
description: Abracon Corporation
|
||||
"^abt,.*":
|
||||
description: ShenZhen Asia Better Technology Ltd.
|
||||
"^acer,.*":
|
||||
description: Acer Inc.
|
||||
"^acme,.*":
|
||||
|
@ -292,6 +292,27 @@ Contact: Daniel Vetter, Noralf Tronnes
|
||||
|
||||
Level: Advanced
|
||||
|
||||
Garbage collect fbdev scrolling acceleration
|
||||
--------------------------------------------
|
||||
|
||||
Scroll acceleration is disabled in fbcon by hard-wiring p->scrollmode =
|
||||
SCROLL_REDRAW. There's a ton of code this will allow us to remove:
|
||||
|
||||
- lots of code in fbcon.c
|
||||
|
||||
- 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)
|
||||
|
||||
- fb_copyarea is unused after this, and can be deleted from all drivers
|
||||
|
||||
Note that not all acceleration code can be deleted, since clearing and cursor
|
||||
support is still accelerated, which might be good candidates for further
|
||||
deletion projects.
|
||||
|
||||
Contact: Daniel Vetter
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
idr_init_base()
|
||||
---------------
|
||||
|
||||
|
@ -325,7 +325,7 @@ static void armada_overlay_reset(struct drm_plane *plane)
|
||||
}
|
||||
}
|
||||
|
||||
struct drm_plane_state *
|
||||
static struct drm_plane_state *
|
||||
armada_overlay_duplicate_state(struct drm_plane *plane)
|
||||
{
|
||||
struct armada_overlay_state *state;
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "atmel_hlcdc_dc.h"
|
||||
|
||||
/**
|
||||
* Atmel HLCDC CRTC state structure
|
||||
* struct atmel_hlcdc_crtc_state - Atmel HLCDC CRTC state structure
|
||||
*
|
||||
* @base: base CRTC state
|
||||
* @output_mode: RGBXXX output mode
|
||||
@ -42,10 +42,10 @@ drm_crtc_state_to_atmel_hlcdc_crtc_state(struct drm_crtc_state *state)
|
||||
}
|
||||
|
||||
/**
|
||||
* Atmel HLCDC CRTC structure
|
||||
* struct atmel_hlcdc_crtc - Atmel HLCDC CRTC structure
|
||||
*
|
||||
* @base: base DRM CRTC structure
|
||||
* @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device
|
||||
* @dc: pointer to the atmel_hlcdc structure provided by the MFD device
|
||||
* @event: pointer to the current page flip event
|
||||
* @id: CRTC id (returned by drm_crtc_index)
|
||||
*/
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "atmel_hlcdc_dc.h"
|
||||
|
||||
/**
|
||||
* Atmel HLCDC Plane state structure.
|
||||
* struct atmel_hlcdc_plane_state - Atmel HLCDC Plane state structure.
|
||||
*
|
||||
* @base: DRM plane state
|
||||
* @crtc_x: x position of the plane relative to the CRTC
|
||||
@ -34,6 +34,7 @@
|
||||
* @disc_y: y discard position
|
||||
* @disc_w: discard width
|
||||
* @disc_h: discard height
|
||||
* @ahb_id: AHB identification number
|
||||
* @bpp: bytes per pixel deduced from pixel_format
|
||||
* @offsets: offsets to apply to the GEM buffers
|
||||
* @xstride: value to add to the pixel pointer between each line
|
||||
@ -280,8 +281,8 @@ atmel_hlcdc_plane_scaler_set_phicoeff(struct atmel_hlcdc_plane *plane,
|
||||
coeff_tab[i]);
|
||||
}
|
||||
|
||||
void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane,
|
||||
struct atmel_hlcdc_plane_state *state)
|
||||
static void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane,
|
||||
struct atmel_hlcdc_plane_state *state)
|
||||
{
|
||||
const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
|
||||
u32 xfactor, yfactor;
|
||||
|
@ -543,7 +543,7 @@ void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
|
||||
EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
|
||||
|
||||
/**
|
||||
* __drm_atomic_helper_private_duplicate_state - copy atomic private state
|
||||
* __drm_atomic_helper_private_obj_duplicate_state - copy atomic private state
|
||||
* @obj: CRTC object
|
||||
* @state: new private object state
|
||||
*
|
||||
|
@ -85,13 +85,15 @@ int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
|
||||
|
||||
drm_mode_copy(&state->mode, mode);
|
||||
state->enable = true;
|
||||
DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
|
||||
mode->name, crtc->base.id, crtc->name, state);
|
||||
drm_dbg_atomic(crtc->dev,
|
||||
"Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
|
||||
mode->name, crtc->base.id, crtc->name, state);
|
||||
} else {
|
||||
memset(&state->mode, 0, sizeof(state->mode));
|
||||
state->enable = false;
|
||||
DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
|
||||
crtc->base.id, crtc->name, state);
|
||||
drm_dbg_atomic(crtc->dev,
|
||||
"Set [NOMODE] for [CRTC:%d:%s] state %p\n",
|
||||
crtc->base.id, crtc->name, state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -128,31 +130,35 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
|
||||
int ret;
|
||||
|
||||
if (blob->length != sizeof(struct drm_mode_modeinfo)) {
|
||||
DRM_DEBUG_ATOMIC("[CRTC:%d:%s] bad mode blob length: %zu\n",
|
||||
crtc->base.id, crtc->name,
|
||||
blob->length);
|
||||
drm_dbg_atomic(crtc->dev,
|
||||
"[CRTC:%d:%s] bad mode blob length: %zu\n",
|
||||
crtc->base.id, crtc->name,
|
||||
blob->length);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = drm_mode_convert_umode(crtc->dev,
|
||||
&state->mode, blob->data);
|
||||
if (ret) {
|
||||
DRM_DEBUG_ATOMIC("[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n",
|
||||
crtc->base.id, crtc->name,
|
||||
ret, drm_get_mode_status_name(state->mode.status));
|
||||
drm_dbg_atomic(crtc->dev,
|
||||
"[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n",
|
||||
crtc->base.id, crtc->name,
|
||||
ret, drm_get_mode_status_name(state->mode.status));
|
||||
drm_mode_debug_printmodeline(&state->mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
state->mode_blob = drm_property_blob_get(blob);
|
||||
state->enable = true;
|
||||
DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
|
||||
state->mode.name, crtc->base.id, crtc->name,
|
||||
state);
|
||||
drm_dbg_atomic(crtc->dev,
|
||||
"Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
|
||||
state->mode.name, crtc->base.id, crtc->name,
|
||||
state);
|
||||
} else {
|
||||
state->enable = false;
|
||||
DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
|
||||
crtc->base.id, crtc->name, state);
|
||||
drm_dbg_atomic(crtc->dev,
|
||||
"Set [NOMODE] for [CRTC:%d:%s] state %p\n",
|
||||
crtc->base.id, crtc->name, state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -202,12 +208,14 @@ drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
|
||||
}
|
||||
|
||||
if (crtc)
|
||||
DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n",
|
||||
plane->base.id, plane->name, plane_state,
|
||||
crtc->base.id, crtc->name);
|
||||
drm_dbg_atomic(plane->dev,
|
||||
"Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n",
|
||||
plane->base.id, plane->name, plane_state,
|
||||
crtc->base.id, crtc->name);
|
||||
else
|
||||
DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [NOCRTC]\n",
|
||||
plane->base.id, plane->name, plane_state);
|
||||
drm_dbg_atomic(plane->dev,
|
||||
"Link [PLANE:%d:%s] state %p to [NOCRTC]\n",
|
||||
plane->base.id, plane->name, plane_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -230,12 +238,14 @@ drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
|
||||
struct drm_plane *plane = plane_state->plane;
|
||||
|
||||
if (fb)
|
||||
DRM_DEBUG_ATOMIC("Set [FB:%d] for [PLANE:%d:%s] state %p\n",
|
||||
fb->base.id, plane->base.id, plane->name,
|
||||
plane_state);
|
||||
drm_dbg_atomic(plane->dev,
|
||||
"Set [FB:%d] for [PLANE:%d:%s] state %p\n",
|
||||
fb->base.id, plane->base.id, plane->name,
|
||||
plane_state);
|
||||
else
|
||||
DRM_DEBUG_ATOMIC("Set [NOFB] for [PLANE:%d:%s] state %p\n",
|
||||
plane->base.id, plane->name, plane_state);
|
||||
drm_dbg_atomic(plane->dev,
|
||||
"Set [NOFB] for [PLANE:%d:%s] state %p\n",
|
||||
plane->base.id, plane->name, plane_state);
|
||||
|
||||
drm_framebuffer_assign(&plane_state->fb, fb);
|
||||
}
|
||||
@ -324,13 +334,15 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
|
||||
drm_connector_get(conn_state->connector);
|
||||
conn_state->crtc = crtc;
|
||||
|
||||
DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n",
|
||||
connector->base.id, connector->name,
|
||||
conn_state, crtc->base.id, crtc->name);
|
||||
drm_dbg_atomic(connector->dev,
|
||||
"Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n",
|
||||
connector->base.id, connector->name,
|
||||
conn_state, crtc->base.id, crtc->name);
|
||||
} else {
|
||||
DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n",
|
||||
connector->base.id, connector->name,
|
||||
conn_state);
|
||||
drm_dbg_atomic(connector->dev,
|
||||
"Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n",
|
||||
connector->base.id, connector->name,
|
||||
conn_state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -474,9 +486,10 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
|
||||
} else if (crtc->funcs->atomic_set_property) {
|
||||
return crtc->funcs->atomic_set_property(crtc, state, property, val);
|
||||
} else {
|
||||
DRM_DEBUG_ATOMIC("[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
|
||||
crtc->base.id, crtc->name,
|
||||
property->base.id, property->name);
|
||||
drm_dbg_atomic(crtc->dev,
|
||||
"[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
|
||||
crtc->base.id, crtc->name,
|
||||
property->base.id, property->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -570,8 +583,9 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
|
||||
state->pixel_blend_mode = val;
|
||||
} else if (property == plane->rotation_property) {
|
||||
if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) {
|
||||
DRM_DEBUG_ATOMIC("[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n",
|
||||
plane->base.id, plane->name, val);
|
||||
drm_dbg_atomic(plane->dev,
|
||||
"[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n",
|
||||
plane->base.id, plane->name, val);
|
||||
return -EINVAL;
|
||||
}
|
||||
state->rotation = val;
|
||||
@ -595,9 +609,10 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
|
||||
return plane->funcs->atomic_set_property(plane, state,
|
||||
property, val);
|
||||
} else {
|
||||
DRM_DEBUG_ATOMIC("[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
|
||||
plane->base.id, plane->name,
|
||||
property->base.id, property->name);
|
||||
drm_dbg_atomic(plane->dev,
|
||||
"[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
|
||||
plane->base.id, plane->name,
|
||||
property->base.id, property->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -665,17 +680,20 @@ static int drm_atomic_set_writeback_fb_for_connector(
|
||||
struct drm_framebuffer *fb)
|
||||
{
|
||||
int ret;
|
||||
struct drm_connector *conn = conn_state->connector;
|
||||
|
||||
ret = drm_writeback_set_fb(conn_state, fb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (fb)
|
||||
DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n",
|
||||
fb->base.id, conn_state);
|
||||
drm_dbg_atomic(conn->dev,
|
||||
"Set [FB:%d] for connector state %p\n",
|
||||
fb->base.id, conn_state);
|
||||
else
|
||||
DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n",
|
||||
conn_state);
|
||||
drm_dbg_atomic(conn->dev,
|
||||
"Set [NOFB] for connector state %p\n",
|
||||
conn_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -782,9 +800,10 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
|
||||
return connector->funcs->atomic_set_property(connector,
|
||||
state, property, val);
|
||||
} else {
|
||||
DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
|
||||
connector->base.id, connector->name,
|
||||
property->base.id, property->name);
|
||||
drm_dbg_atomic(connector->dev,
|
||||
"[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
|
||||
connector->base.id, connector->name,
|
||||
property->base.id, property->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1282,7 +1301,7 @@ static void complete_signaling(struct drm_device *dev,
|
||||
/* If this fails log error to the user */
|
||||
if (fence_state[i].out_fence_ptr &&
|
||||
put_user(-1, fence_state[i].out_fence_ptr))
|
||||
DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
|
||||
drm_dbg_atomic(dev, "Couldn't clear out_fence_ptr\n");
|
||||
}
|
||||
|
||||
kfree(fence_state);
|
||||
@ -1311,22 +1330,35 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
|
||||
* though this may be a bit overkill, since legacy userspace
|
||||
* wouldn't know how to call this ioctl)
|
||||
*/
|
||||
if (!file_priv->atomic)
|
||||
if (!file_priv->atomic) {
|
||||
drm_dbg_atomic(dev,
|
||||
"commit failed: atomic cap not enabled\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS)
|
||||
if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS) {
|
||||
drm_dbg_atomic(dev, "commit failed: invalid flag\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg->reserved)
|
||||
if (arg->reserved) {
|
||||
drm_dbg_atomic(dev, "commit failed: reserved field set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC)
|
||||
if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) {
|
||||
drm_dbg_atomic(dev,
|
||||
"commit failed: invalid flag DRM_MODE_PAGE_FLIP_ASYNC\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* can't test and expect an event at the same time. */
|
||||
if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
|
||||
(arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
|
||||
(arg->flags & DRM_MODE_PAGE_FLIP_EVENT)) {
|
||||
drm_dbg_atomic(dev,
|
||||
"commit failed: page-flip event requested with test-only commit\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
state = drm_atomic_state_alloc(dev);
|
||||
if (!state)
|
||||
|
@ -1432,7 +1432,8 @@ void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame,
|
||||
EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
|
||||
|
||||
/**
|
||||
* drm_mode_attach_tv_margin_properties - attach TV connector margin properties
|
||||
* drm_connector_attach_tv_margin_properties - attach TV connector margin
|
||||
* properties
|
||||
* @connector: DRM connector
|
||||
*
|
||||
* Called by a driver when it needs to attach TV margin props to a connector.
|
||||
|
@ -1161,7 +1161,7 @@ drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
|
||||
EXPORT_SYMBOL(drm_dp_subconnector_type);
|
||||
|
||||
/**
|
||||
* drm_mode_set_dp_subconnector_property - set subconnector for DP connector
|
||||
* drm_dp_set_subconnector_property - set subconnector for DP connector
|
||||
* @connector: connector to set property on
|
||||
* @status: connector status
|
||||
* @dpcd: DisplayPort configuration data
|
||||
|
@ -3260,7 +3260,7 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
|
||||
{
|
||||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
u8 nonce[7];
|
||||
int len, ret;
|
||||
int ret;
|
||||
|
||||
txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
|
||||
if (!txmsg)
|
||||
@ -3281,7 +3281,7 @@ int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
|
||||
*/
|
||||
txmsg->dst = mgr->mst_primary;
|
||||
|
||||
len = build_query_stream_enc_status(txmsg, port->vcpi.vcpi, nonce);
|
||||
build_query_stream_enc_status(txmsg, port->vcpi.vcpi, nonce);
|
||||
|
||||
drm_dp_queue_down_tx(mgr, txmsg);
|
||||
|
||||
|
@ -552,7 +552,7 @@ out:
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_getfb2 - get extended FB info
|
||||
* drm_mode_getfb2_ioctl - get extended FB info
|
||||
* @dev: drm device for the ioctl
|
||||
* @data: data pointer for the ioctl
|
||||
* @file_priv: drm file for the ioctl call
|
||||
|
@ -867,7 +867,7 @@ err:
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_gem_open - implementation of the GEM_OPEN ioctl
|
||||
* drm_gem_open_ioctl - implementation of the GEM_OPEN ioctl
|
||||
* @dev: drm_device
|
||||
* @data: ioctl data
|
||||
* @file_priv: drm file-private structure
|
||||
@ -912,7 +912,7 @@ err:
|
||||
}
|
||||
|
||||
/**
|
||||
* gem_gem_open - initalizes GEM file-private structures at devnode open time
|
||||
* drm_gem_open - initalizes GEM file-private structures at devnode open time
|
||||
* @dev: drm_device which is being opened by userspace
|
||||
* @file_private: drm file-private structure to set up
|
||||
*
|
||||
|
@ -617,7 +617,7 @@ static void drm_gem_vram_object_free(struct drm_gem_object *gem)
|
||||
*/
|
||||
|
||||
/**
|
||||
* drm_gem_vram_driver_create_dumb() - \
|
||||
* drm_gem_vram_driver_dumb_create() - \
|
||||
Implements &struct drm_driver.dumb_create
|
||||
* @file: the DRM file
|
||||
* @dev: the DRM device
|
||||
|
@ -115,7 +115,7 @@ void drm_mode_object_unregister(struct drm_device *dev,
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_lease_required - check types which must be leased to be used
|
||||
* drm_mode_object_lease_required - check types which must be leased to be used
|
||||
* @type: type of object
|
||||
*
|
||||
* Returns whether the provided type of drm_mode_object must
|
||||
|
@ -1889,7 +1889,7 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev,
|
||||
EXPORT_SYMBOL(drm_mode_create_from_cmdline_mode);
|
||||
|
||||
/**
|
||||
* drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
|
||||
* drm_mode_convert_to_umode - convert a drm_display_mode into a modeinfo
|
||||
* @out: drm_mode_modeinfo struct to return to the user
|
||||
* @in: drm_display_mode to use
|
||||
*
|
||||
@ -1941,7 +1941,7 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_crtc_convert_umode - convert a modeinfo into a drm_display_mode
|
||||
* drm_mode_convert_umode - convert a modeinfo into a drm_display_mode
|
||||
* @dev: drm device
|
||||
* @out: drm_display_mode to return to the user
|
||||
* @in: drm_mode_modeinfo to use
|
||||
|
@ -125,7 +125,7 @@ ssize_t drm_scdc_write(struct i2c_adapter *adapter, u8 offset,
|
||||
EXPORT_SYMBOL(drm_scdc_write);
|
||||
|
||||
/**
|
||||
* drm_scdc_check_scrambling_status - what is status of scrambling?
|
||||
* drm_scdc_get_scrambling_status - what is status of scrambling?
|
||||
* @adapter: I2C adapter for DDC channel
|
||||
*
|
||||
* Reads the scrambler status over SCDC, and checks the
|
||||
|
@ -346,6 +346,7 @@ static void decon_win_set_colkey(struct decon_context *ctx, unsigned int win)
|
||||
/**
|
||||
* shadow_protect_win() - disable updating values from shadow registers at vsync
|
||||
*
|
||||
* @ctx: display and enhancement controller context
|
||||
* @win: window to protect registers for
|
||||
* @protect: 1 to protect (disable updates)
|
||||
*/
|
||||
|
@ -725,6 +725,7 @@ static void fimd_win_set_colkey(struct fimd_context *ctx, unsigned int win)
|
||||
/**
|
||||
* shadow_protect_win() - disable updating values from shadow registers at vsync
|
||||
*
|
||||
* @ctx: local driver data
|
||||
* @win: window to protect registers for
|
||||
* @protect: 1 to protect (disable updates)
|
||||
*/
|
||||
|
@ -118,6 +118,7 @@ struct gsc_context {
|
||||
* struct gsc_driverdata - per device type driver data for init time.
|
||||
*
|
||||
* @limits: picture size limits array
|
||||
* @num_limits: number of items in the aforementioned array
|
||||
* @clk_names: names of clocks needed by this variant
|
||||
* @num_clocks: the number of clocks needed by this variant
|
||||
*/
|
||||
|
@ -58,295 +58,3 @@ void psb_spank(struct drm_psb_private *dev_priv)
|
||||
(void) PSB_RSGX32(PSB_CR_BIF_CTRL);
|
||||
PSB_WSGX32(dev_priv->gtt.gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
|
||||
}
|
||||
|
||||
/**
|
||||
* psb2_2d_wait_available - wait for FIFO room
|
||||
* @dev_priv: our DRM device
|
||||
* @size: size (in dwords) of the command we want to issue
|
||||
*
|
||||
* Wait until there is room to load the FIFO with our data. If the
|
||||
* device is not responding then reset it
|
||||
*/
|
||||
static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
|
||||
unsigned size)
|
||||
{
|
||||
uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
|
||||
unsigned long t = jiffies + HZ;
|
||||
|
||||
while (avail < size) {
|
||||
avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
|
||||
if (time_after(jiffies, t)) {
|
||||
psb_spank(dev_priv);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* psb_2d_submit - submit a 2D command
|
||||
* @dev_priv: our DRM device
|
||||
* @cmdbuf: command to issue
|
||||
* @size: length (in dwords)
|
||||
*
|
||||
* Issue one or more 2D commands to the accelerator. This needs to be
|
||||
* serialized later when we add the GEM interfaces for acceleration
|
||||
*/
|
||||
static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
|
||||
unsigned size)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
unsigned submit_size;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->lock_2d, flags);
|
||||
while (size > 0) {
|
||||
submit_size = (size < 0x60) ? size : 0x60;
|
||||
size -= submit_size;
|
||||
ret = psb_2d_wait_available(dev_priv, submit_size);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
submit_size <<= 2;
|
||||
|
||||
for (i = 0; i < submit_size; i += 4)
|
||||
PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i);
|
||||
|
||||
(void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
|
||||
}
|
||||
spin_unlock_irqrestore(&dev_priv->lock_2d, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* psb_accel_2d_copy_direction - compute blit order
|
||||
* @xdir: X direction of move
|
||||
* @ydir: Y direction of move
|
||||
*
|
||||
* Compute the correct order setings to ensure that an overlapping blit
|
||||
* correctly copies all the pixels.
|
||||
*/
|
||||
static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
|
||||
{
|
||||
if (xdir < 0)
|
||||
return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL :
|
||||
PSB_2D_COPYORDER_TR2BL;
|
||||
else
|
||||
return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR :
|
||||
PSB_2D_COPYORDER_TL2BR;
|
||||
}
|
||||
|
||||
/**
|
||||
* psb_accel_2d_copy - accelerated 2D copy
|
||||
* @dev_priv: our DRM device
|
||||
* @src_offset in bytes
|
||||
* @src_stride in bytes
|
||||
* @src_format psb 2D format defines
|
||||
* @dst_offset in bytes
|
||||
* @dst_stride in bytes
|
||||
* @dst_format psb 2D format defines
|
||||
* @src_x offset in pixels
|
||||
* @src_y offset in pixels
|
||||
* @dst_x offset in pixels
|
||||
* @dst_y offset in pixels
|
||||
* @size_x of the copied area
|
||||
* @size_y of the copied area
|
||||
*
|
||||
* Format and issue a 2D accelerated copy command.
|
||||
*/
|
||||
static int psb_accel_2d_copy(struct drm_psb_private *dev_priv,
|
||||
uint32_t src_offset, uint32_t src_stride,
|
||||
uint32_t src_format, uint32_t dst_offset,
|
||||
uint32_t dst_stride, uint32_t dst_format,
|
||||
uint16_t src_x, uint16_t src_y,
|
||||
uint16_t dst_x, uint16_t dst_y,
|
||||
uint16_t size_x, uint16_t size_y)
|
||||
{
|
||||
uint32_t blit_cmd;
|
||||
uint32_t buffer[10];
|
||||
uint32_t *buf;
|
||||
uint32_t direction;
|
||||
|
||||
buf = buffer;
|
||||
|
||||
direction =
|
||||
psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y);
|
||||
|
||||
if (direction == PSB_2D_COPYORDER_BR2TL ||
|
||||
direction == PSB_2D_COPYORDER_TR2BL) {
|
||||
src_x += size_x - 1;
|
||||
dst_x += size_x - 1;
|
||||
}
|
||||
if (direction == PSB_2D_COPYORDER_BR2TL ||
|
||||
direction == PSB_2D_COPYORDER_BL2TR) {
|
||||
src_y += size_y - 1;
|
||||
dst_y += size_y - 1;
|
||||
}
|
||||
|
||||
blit_cmd =
|
||||
PSB_2D_BLIT_BH |
|
||||
PSB_2D_ROT_NONE |
|
||||
PSB_2D_DSTCK_DISABLE |
|
||||
PSB_2D_SRCCK_DISABLE |
|
||||
PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction;
|
||||
|
||||
*buf++ = PSB_2D_FENCE_BH;
|
||||
*buf++ =
|
||||
PSB_2D_DST_SURF_BH | dst_format | (dst_stride <<
|
||||
PSB_2D_DST_STRIDE_SHIFT);
|
||||
*buf++ = dst_offset;
|
||||
*buf++ =
|
||||
PSB_2D_SRC_SURF_BH | src_format | (src_stride <<
|
||||
PSB_2D_SRC_STRIDE_SHIFT);
|
||||
*buf++ = src_offset;
|
||||
*buf++ =
|
||||
PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) |
|
||||
(src_y << PSB_2D_SRCOFF_YSTART_SHIFT);
|
||||
*buf++ = blit_cmd;
|
||||
*buf++ =
|
||||
(dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y <<
|
||||
PSB_2D_DST_YSTART_SHIFT);
|
||||
*buf++ =
|
||||
(size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y <<
|
||||
PSB_2D_DST_YSIZE_SHIFT);
|
||||
*buf++ = PSB_2D_FLUSH_BH;
|
||||
|
||||
return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* psbfb_copyarea_accel - copyarea acceleration for /dev/fb
|
||||
* @info: our framebuffer
|
||||
* @a: copyarea parameters from the framebuffer core
|
||||
*
|
||||
* Perform a 2D copy via the accelerator
|
||||
*/
|
||||
static void psbfb_copyarea_accel(struct fb_info *info,
|
||||
const struct fb_copyarea *a)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
struct drm_device *dev;
|
||||
struct drm_psb_private *dev_priv;
|
||||
uint32_t offset;
|
||||
uint32_t stride;
|
||||
uint32_t src_format;
|
||||
uint32_t dst_format;
|
||||
|
||||
if (!fb)
|
||||
return;
|
||||
|
||||
dev = fb->dev;
|
||||
dev_priv = dev->dev_private;
|
||||
offset = to_gtt_range(fb->obj[0])->offset;
|
||||
stride = fb->pitches[0];
|
||||
|
||||
switch (fb->format->depth) {
|
||||
case 8:
|
||||
src_format = PSB_2D_SRC_332RGB;
|
||||
dst_format = PSB_2D_DST_332RGB;
|
||||
break;
|
||||
case 15:
|
||||
src_format = PSB_2D_SRC_555RGB;
|
||||
dst_format = PSB_2D_DST_555RGB;
|
||||
break;
|
||||
case 16:
|
||||
src_format = PSB_2D_SRC_565RGB;
|
||||
dst_format = PSB_2D_DST_565RGB;
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
/* this is wrong but since we don't do blending its okay */
|
||||
src_format = PSB_2D_SRC_8888ARGB;
|
||||
dst_format = PSB_2D_DST_8888ARGB;
|
||||
break;
|
||||
default:
|
||||
/* software fallback */
|
||||
drm_fb_helper_cfb_copyarea(info, a);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gma_power_begin(dev, false)) {
|
||||
drm_fb_helper_cfb_copyarea(info, a);
|
||||
return;
|
||||
}
|
||||
psb_accel_2d_copy(dev_priv,
|
||||
offset, stride, src_format,
|
||||
offset, stride, dst_format,
|
||||
a->sx, a->sy, a->dx, a->dy, a->width, a->height);
|
||||
gma_power_end(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* psbfb_copyarea - 2D copy interface
|
||||
* @info: our framebuffer
|
||||
* @region: region to copy
|
||||
*
|
||||
* Copy an area of the framebuffer console either by the accelerator
|
||||
* or directly using the cfb helpers according to the request
|
||||
*/
|
||||
void psbfb_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *region)
|
||||
{
|
||||
if (unlikely(info->state != FBINFO_STATE_RUNNING))
|
||||
return;
|
||||
|
||||
/* Avoid the 8 pixel erratum */
|
||||
if (region->width == 8 || region->height == 8 ||
|
||||
(info->flags & FBINFO_HWACCEL_DISABLED))
|
||||
return drm_fb_helper_cfb_copyarea(info, region);
|
||||
|
||||
psbfb_copyarea_accel(info, region);
|
||||
}
|
||||
|
||||
/**
|
||||
* psbfb_sync - synchronize 2D
|
||||
* @info: our framebuffer
|
||||
*
|
||||
* Wait for the 2D engine to quiesce so that we can do CPU
|
||||
* access to the framebuffer again
|
||||
*/
|
||||
int psbfb_sync(struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
struct drm_device *dev = fb->dev;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
unsigned long _end = jiffies + HZ;
|
||||
int busy = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->lock_2d, flags);
|
||||
/*
|
||||
* First idle the 2D engine.
|
||||
*/
|
||||
|
||||
if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) &&
|
||||
((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0))
|
||||
goto out;
|
||||
|
||||
do {
|
||||
busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
|
||||
cpu_relax();
|
||||
} while (busy && !time_after_eq(jiffies, _end));
|
||||
|
||||
if (busy)
|
||||
busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
|
||||
if (busy)
|
||||
goto out;
|
||||
|
||||
do {
|
||||
busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
|
||||
_PSB_C2B_STATUS_BUSY) != 0);
|
||||
cpu_relax();
|
||||
} while (busy && !time_after_eq(jiffies, _end));
|
||||
if (busy)
|
||||
busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
|
||||
_PSB_C2B_STATUS_BUSY) != 0);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&dev_priv->lock_2d, flags);
|
||||
return (busy) ? -EBUSY : 0;
|
||||
}
|
||||
|
@ -584,7 +584,6 @@ static int cdv_chip_setup(struct drm_device *dev)
|
||||
|
||||
const struct psb_ops cdv_chip_ops = {
|
||||
.name = "GMA3600/3650",
|
||||
.accel_2d = 0,
|
||||
.pipes = 2,
|
||||
.crtcs = 2,
|
||||
.hdmi_mask = (1 << 0) | (1 << 1),
|
||||
|
@ -76,27 +76,6 @@ static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
struct drm_device *dev = fb->dev;
|
||||
struct gtt_range *gtt = to_gtt_range(fb->obj[0]);
|
||||
|
||||
/*
|
||||
* We have to poke our nose in here. The core fb code assumes
|
||||
* panning is part of the hardware that can be invoked before
|
||||
* the actual fb is mapped. In our case that isn't quite true.
|
||||
*/
|
||||
if (gtt->npage) {
|
||||
/* GTT roll shifts in 4K pages, we need to shift the right
|
||||
number of pages */
|
||||
int pages = info->fix.line_length >> 12;
|
||||
psb_gtt_roll(dev, gtt, var->yoffset * pages);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static vm_fault_t psbfb_vm_fault(struct vm_fault *vmf)
|
||||
{
|
||||
struct vm_area_struct *vma = vmf->vma;
|
||||
@ -165,28 +144,6 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fb_ops psbfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
.fb_setcolreg = psbfb_setcolreg,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = psbfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_mmap = psbfb_mmap,
|
||||
.fb_sync = psbfb_sync,
|
||||
};
|
||||
|
||||
static const struct fb_ops psbfb_roll_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
.fb_setcolreg = psbfb_setcolreg,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_pan_display = psbfb_pan,
|
||||
.fb_mmap = psbfb_mmap,
|
||||
};
|
||||
|
||||
static const struct fb_ops psbfb_unaccel_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
@ -312,8 +269,6 @@ static int psbfb_create(struct drm_fb_helper *fb_helper,
|
||||
int ret;
|
||||
struct gtt_range *backing;
|
||||
u32 bpp, depth;
|
||||
int gtt_roll = 0;
|
||||
int pitch_lines = 0;
|
||||
|
||||
mode_cmd.width = sizes->surface_width;
|
||||
mode_cmd.height = sizes->surface_height;
|
||||
@ -324,50 +279,15 @@ static int psbfb_create(struct drm_fb_helper *fb_helper,
|
||||
if (bpp == 24)
|
||||
bpp = 32;
|
||||
|
||||
do {
|
||||
/*
|
||||
* Acceleration via the GTT requires pitch to be
|
||||
* power of two aligned. Preferably page but less
|
||||
* is ok with some fonts
|
||||
*/
|
||||
mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096 >> pitch_lines);
|
||||
mode_cmd.pitches[0] = ALIGN(mode_cmd.width * DIV_ROUND_UP(bpp, 8), 64);
|
||||
|
||||
size = mode_cmd.pitches[0] * mode_cmd.height;
|
||||
size = ALIGN(size, PAGE_SIZE);
|
||||
size = mode_cmd.pitches[0] * mode_cmd.height;
|
||||
size = ALIGN(size, PAGE_SIZE);
|
||||
|
||||
/* Allocate the fb in the GTT with stolen page backing */
|
||||
backing = psbfb_alloc(dev, size);
|
||||
|
||||
if (pitch_lines)
|
||||
pitch_lines *= 2;
|
||||
else
|
||||
pitch_lines = 1;
|
||||
gtt_roll++;
|
||||
} while (backing == NULL && pitch_lines <= 16);
|
||||
|
||||
/* The final pitch we accepted if we succeeded */
|
||||
pitch_lines /= 2;
|
||||
|
||||
if (backing == NULL) {
|
||||
/*
|
||||
* We couldn't get the space we wanted, fall back to the
|
||||
* display engine requirement instead. The HW requires
|
||||
* the pitch to be 64 byte aligned
|
||||
*/
|
||||
|
||||
gtt_roll = 0; /* Don't use GTT accelerated scrolling */
|
||||
pitch_lines = 64;
|
||||
|
||||
mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64);
|
||||
|
||||
size = mode_cmd.pitches[0] * mode_cmd.height;
|
||||
size = ALIGN(size, PAGE_SIZE);
|
||||
|
||||
/* Allocate the framebuffer in the GTT with stolen page backing */
|
||||
backing = psbfb_alloc(dev, size);
|
||||
if (backing == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* Allocate the framebuffer in the GTT with stolen page backing */
|
||||
backing = psbfb_alloc(dev, size);
|
||||
if (backing == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(dev_priv->vram_addr + backing->offset, 0, size);
|
||||
|
||||
@ -387,17 +307,11 @@ static int psbfb_create(struct drm_fb_helper *fb_helper,
|
||||
|
||||
fb_helper->fb = fb;
|
||||
|
||||
if (dev_priv->ops->accel_2d && pitch_lines > 8) /* 2D engine */
|
||||
info->fbops = &psbfb_ops;
|
||||
else if (gtt_roll) { /* GTT rolling seems best */
|
||||
info->fbops = &psbfb_roll_ops;
|
||||
info->flags |= FBINFO_HWACCEL_YPAN;
|
||||
} else /* Software */
|
||||
info->fbops = &psbfb_unaccel_ops;
|
||||
info->fbops = &psbfb_unaccel_ops;
|
||||
|
||||
info->fix.smem_start = dev->mode_config.fb_base;
|
||||
info->fix.smem_len = size;
|
||||
info->fix.ywrapstep = gtt_roll;
|
||||
info->fix.ywrapstep = 0;
|
||||
info->fix.ypanstep = 0;
|
||||
|
||||
/* Accessed stolen memory directly */
|
||||
|
@ -96,16 +96,12 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r,
|
||||
}
|
||||
|
||||
/* Write our page entries into the GTT itself */
|
||||
for (i = r->roll; i < r->npage; i++) {
|
||||
pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
|
||||
PSB_MMU_CACHED_MEMORY);
|
||||
iowrite32(pte, gtt_slot++);
|
||||
}
|
||||
for (i = 0; i < r->roll; i++) {
|
||||
for (i = 0; i < r->npage; i++) {
|
||||
pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
|
||||
PSB_MMU_CACHED_MEMORY);
|
||||
iowrite32(pte, gtt_slot++);
|
||||
}
|
||||
|
||||
/* Make sure all the entries are set before we return */
|
||||
ioread32(gtt_slot - 1);
|
||||
|
||||
@ -140,49 +136,6 @@ static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
|
||||
set_pages_array_wb(r->pages, r->npage);
|
||||
}
|
||||
|
||||
/**
|
||||
* psb_gtt_roll - set scrolling position
|
||||
* @dev: our DRM device
|
||||
* @r: the gtt mapping we are using
|
||||
* @roll: roll offset
|
||||
*
|
||||
* Roll an existing pinned mapping by moving the pages through the GTT.
|
||||
* This allows us to implement hardware scrolling on the consoles without
|
||||
* a 2D engine
|
||||
*/
|
||||
void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll)
|
||||
{
|
||||
u32 __iomem *gtt_slot;
|
||||
u32 pte;
|
||||
int i;
|
||||
|
||||
if (roll >= r->npage) {
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
r->roll = roll;
|
||||
|
||||
/* Not currently in the GTT - no worry we will write the mapping at
|
||||
the right position when it gets pinned */
|
||||
if (!r->stolen && !r->in_gart)
|
||||
return;
|
||||
|
||||
gtt_slot = psb_gtt_entry(dev, r);
|
||||
|
||||
for (i = r->roll; i < r->npage; i++) {
|
||||
pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
|
||||
PSB_MMU_CACHED_MEMORY);
|
||||
iowrite32(pte, gtt_slot++);
|
||||
}
|
||||
for (i = 0; i < r->roll; i++) {
|
||||
pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]),
|
||||
PSB_MMU_CACHED_MEMORY);
|
||||
iowrite32(pte, gtt_slot++);
|
||||
}
|
||||
ioread32(gtt_slot - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* psb_gtt_attach_pages - attach and pin GEM pages
|
||||
* @gt: the gtt range
|
||||
@ -346,7 +299,6 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
|
||||
gt->resource.name = name;
|
||||
gt->stolen = backed;
|
||||
gt->in_gart = backed;
|
||||
gt->roll = 0;
|
||||
/* Ensure this is set for non GEM objects */
|
||||
gt->gem.dev = dev;
|
||||
ret = allocate_resource(dev_priv->gtt_mem, >->resource,
|
||||
|
@ -37,7 +37,6 @@ struct gtt_range {
|
||||
bool mmapping; /* Is mmappable */
|
||||
struct page **pages; /* Backing pages if present */
|
||||
int npage; /* Number of backing pages */
|
||||
int roll; /* Roll applied to the GTT entries */
|
||||
};
|
||||
|
||||
#define to_gtt_range(x) container_of(x, struct gtt_range, gem)
|
||||
@ -49,7 +48,5 @@ extern void psb_gtt_kref_put(struct gtt_range *gt);
|
||||
extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt);
|
||||
extern int psb_gtt_pin(struct gtt_range *gt);
|
||||
extern void psb_gtt_unpin(struct gtt_range *gt);
|
||||
extern void psb_gtt_roll(struct drm_device *dev,
|
||||
struct gtt_range *gt, int roll);
|
||||
extern int psb_gtt_restore(struct drm_device *dev);
|
||||
#endif
|
||||
|
@ -536,7 +536,6 @@ static int mdfld_chip_setup(struct drm_device *dev)
|
||||
|
||||
const struct psb_ops mdfld_chip_ops = {
|
||||
.name = "mdfld",
|
||||
.accel_2d = 0,
|
||||
.pipes = 3,
|
||||
.crtcs = 3,
|
||||
.lvds_mask = (1 << 1),
|
||||
|
@ -536,7 +536,6 @@ static void oaktrail_teardown(struct drm_device *dev)
|
||||
|
||||
const struct psb_ops oaktrail_chip_ops = {
|
||||
.name = "Oaktrail",
|
||||
.accel_2d = 1,
|
||||
.pipes = 2,
|
||||
.crtcs = 2,
|
||||
.hdmi_mask = (1 << 1),
|
||||
|
@ -318,7 +318,6 @@ static void psb_chip_teardown(struct drm_device *dev)
|
||||
|
||||
const struct psb_ops psb_chip_ops = {
|
||||
.name = "Poulsbo",
|
||||
.accel_2d = 1,
|
||||
.pipes = 2,
|
||||
.crtcs = 2,
|
||||
.hdmi_mask = (1 << 0),
|
||||
|
@ -124,7 +124,6 @@ static int psb_do_init(struct drm_device *dev)
|
||||
(stolen_gtt << PAGE_SHIFT) * 1024;
|
||||
|
||||
spin_lock_init(&dev_priv->irqmask_lock);
|
||||
spin_lock_init(&dev_priv->lock_2d);
|
||||
|
||||
PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
|
||||
PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
|
||||
|
@ -576,9 +576,6 @@ struct drm_psb_private {
|
||||
|
||||
struct drm_fb_helper *fb_helper;
|
||||
|
||||
/* 2D acceleration */
|
||||
spinlock_t lock_2d;
|
||||
|
||||
/* Panel brightness */
|
||||
int brightness;
|
||||
int brightness_adjusted;
|
||||
@ -615,7 +612,6 @@ struct drm_psb_private {
|
||||
/* Operations for each board type */
|
||||
struct psb_ops {
|
||||
const char *name;
|
||||
unsigned int accel_2d:1;
|
||||
int pipes; /* Number of output pipes */
|
||||
int crtcs; /* Number of CRTCs */
|
||||
int sgx_offset; /* Base offset of SGX device */
|
||||
@ -696,9 +692,6 @@ extern int psbfb_probed(struct drm_device *dev);
|
||||
extern int psbfb_remove(struct drm_device *dev,
|
||||
struct drm_framebuffer *fb);
|
||||
/* accel_2d.c */
|
||||
extern void psbfb_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *region);
|
||||
extern int psbfb_sync(struct fb_info *info);
|
||||
extern void psb_spank(struct drm_psb_private *dev_priv);
|
||||
|
||||
/* psb_reset.c */
|
||||
|
@ -4587,7 +4587,7 @@ void intel_dpll_sanitize_state(struct drm_i915_private *i915)
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_shared_dpll_dump_hw_state - write hw_state to dmesg
|
||||
* intel_dpll_dump_hw_state - write hw_state to dmesg
|
||||
* @dev_priv: i915 drm device
|
||||
* @hw_state: hw state to be written to the log
|
||||
*
|
||||
|
@ -238,7 +238,7 @@ found:
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_gem_evict_for_vma - Evict vmas to make room for binding a new one
|
||||
* i915_gem_evict_for_node - Evict vmas to make room for binding a new one
|
||||
* @vm: address space to evict from
|
||||
* @target: range (and color) to evict for
|
||||
* @flags: additional flags to control the eviction algorithm
|
||||
|
@ -625,7 +625,8 @@ static int append_oa_sample(struct i915_perf_stream *stream,
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all buffered OA reports into userspace read() buffer.
|
||||
* gen8_append_oa_reports - Copies all buffered OA reports into
|
||||
* userspace read() buffer.
|
||||
* @stream: An i915-perf stream opened for OA metrics
|
||||
* @buf: destination buffer given by userspace
|
||||
* @count: the number of bytes userspace wants to read
|
||||
@ -917,7 +918,8 @@ static int gen8_oa_read(struct i915_perf_stream *stream,
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all buffered OA reports into userspace read() buffer.
|
||||
* gen7_append_oa_reports - Copies all buffered OA reports into
|
||||
* userspace read() buffer.
|
||||
* @stream: An i915-perf stream opened for OA metrics
|
||||
* @buf: destination buffer given by userspace
|
||||
* @count: the number of bytes userspace wants to read
|
||||
@ -3227,7 +3229,7 @@ static long i915_perf_config_locked(struct i915_perf_stream *stream,
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_perf_ioctl - support ioctl() usage with i915 perf stream FDs
|
||||
* i915_perf_ioctl_locked - support ioctl() usage with i915 perf stream FDs
|
||||
* @stream: An i915 perf stream
|
||||
* @cmd: the ioctl request
|
||||
* @arg: the ioctl data
|
||||
|
@ -35,18 +35,13 @@ static int lima_devfreq_target(struct device *dev, unsigned long *freq,
|
||||
u32 flags)
|
||||
{
|
||||
struct dev_pm_opp *opp;
|
||||
int err;
|
||||
|
||||
opp = devfreq_recommended_opp(dev, freq, flags);
|
||||
if (IS_ERR(opp))
|
||||
return PTR_ERR(opp);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
err = dev_pm_opp_set_rate(dev, *freq);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
return dev_pm_opp_set_rate(dev, *freq);
|
||||
}
|
||||
|
||||
static void lima_devfreq_reset(struct lima_devfreq *devfreq)
|
||||
@ -105,10 +100,7 @@ void lima_devfreq_fini(struct lima_device *ldev)
|
||||
devfreq->devfreq = NULL;
|
||||
}
|
||||
|
||||
if (devfreq->opp_of_table_added) {
|
||||
dev_pm_opp_of_remove_table(ldev->dev);
|
||||
devfreq->opp_of_table_added = false;
|
||||
}
|
||||
dev_pm_opp_of_remove_table(ldev->dev);
|
||||
|
||||
if (devfreq->regulators_opp_table) {
|
||||
dev_pm_opp_put_regulators(devfreq->regulators_opp_table);
|
||||
@ -162,7 +154,6 @@ int lima_devfreq_init(struct lima_device *ldev)
|
||||
ret = dev_pm_opp_of_add_table(dev);
|
||||
if (ret)
|
||||
goto err_fini;
|
||||
ldevfreq->opp_of_table_added = true;
|
||||
|
||||
lima_devfreq_reset(ldevfreq);
|
||||
|
||||
|
@ -18,7 +18,6 @@ struct lima_devfreq {
|
||||
struct opp_table *clkname_opp_table;
|
||||
struct opp_table *regulators_opp_table;
|
||||
struct thermal_cooling_device *cooling;
|
||||
bool opp_of_table_added;
|
||||
|
||||
ktime_t busy_time;
|
||||
ktime_t idle_time;
|
||||
|
@ -255,7 +255,7 @@ static const struct drm_ioctl_desc lima_drm_driver_ioctls[] = {
|
||||
|
||||
DEFINE_DRM_GEM_FOPS(lima_drm_driver_fops);
|
||||
|
||||
/**
|
||||
/*
|
||||
* Changelog:
|
||||
*
|
||||
* - 1.1.0 - add heap buffer support
|
||||
|
@ -224,7 +224,6 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
||||
struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
|
||||
struct lima_device *ldev = pipe->ldev;
|
||||
struct lima_fence *fence;
|
||||
struct dma_fence *ret;
|
||||
int i, err;
|
||||
|
||||
/* after GPU reset */
|
||||
@ -246,7 +245,7 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
|
||||
/* for caller usage of the fence, otherwise irq handler
|
||||
* may consume the fence before caller use it
|
||||
*/
|
||||
ret = dma_fence_get(task->fence);
|
||||
dma_fence_get(task->fence);
|
||||
|
||||
pipe->current_task = task;
|
||||
|
||||
|
@ -30,8 +30,9 @@ struct mtk_disp_color_data {
|
||||
|
||||
/**
|
||||
* struct mtk_disp_color - DISP_COLOR driver structure
|
||||
* @ddp_comp - structure containing type enum and hardware resources
|
||||
* @crtc - associated crtc to report irq events to
|
||||
* @ddp_comp: structure containing type enum and hardware resources
|
||||
* @crtc: associated crtc to report irq events to
|
||||
* @data: platform colour driver data
|
||||
*/
|
||||
struct mtk_disp_color {
|
||||
struct mtk_ddp_comp ddp_comp;
|
||||
|
@ -65,8 +65,9 @@ struct mtk_disp_ovl_data {
|
||||
|
||||
/**
|
||||
* struct mtk_disp_ovl - DISP_OVL driver structure
|
||||
* @ddp_comp - structure containing type enum and hardware resources
|
||||
* @crtc - associated crtc to report vblank events to
|
||||
* @ddp_comp: structure containing type enum and hardware resources
|
||||
* @crtc: associated crtc to report vblank events to
|
||||
* @data: platform data
|
||||
*/
|
||||
struct mtk_disp_ovl {
|
||||
struct mtk_ddp_comp ddp_comp;
|
||||
|
@ -56,8 +56,9 @@ struct mtk_disp_rdma_data {
|
||||
|
||||
/**
|
||||
* struct mtk_disp_rdma - DISP_RDMA driver structure
|
||||
* @ddp_comp - structure containing type enum and hardware resources
|
||||
* @crtc - associated crtc to report irq events to
|
||||
* @ddp_comp: structure containing type enum and hardware resources
|
||||
* @crtc: associated crtc to report irq events to
|
||||
* @data: local driver data
|
||||
*/
|
||||
struct mtk_disp_rdma {
|
||||
struct mtk_ddp_comp ddp_comp;
|
||||
|
@ -522,15 +522,6 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_dpi_encoder_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
drm_encoder_cleanup(encoder);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_funcs mtk_dpi_encoder_funcs = {
|
||||
.destroy = mtk_dpi_encoder_destroy,
|
||||
};
|
||||
|
||||
static int mtk_dpi_bridge_attach(struct drm_bridge *bridge,
|
||||
enum drm_bridge_attach_flags flags)
|
||||
{
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "mtk_drm_gem.h"
|
||||
#include "mtk_drm_plane.h"
|
||||
|
||||
/**
|
||||
/*
|
||||
* struct mtk_drm_crtc - MediaTek specific crtc structure.
|
||||
* @base: crtc object.
|
||||
* @enabled: records whether crtc_enable succeeded
|
||||
@ -34,6 +34,8 @@
|
||||
* @mutex: handle to one of the ten disp_mutex streams
|
||||
* @ddp_comp_nr: number of components in ddp_comp
|
||||
* @ddp_comp: array of pointers the mtk_ddp_comp structures used by this crtc
|
||||
*
|
||||
* TODO: Needs update: this header is missing a bunch of member descriptions.
|
||||
*/
|
||||
struct mtk_drm_crtc {
|
||||
struct drm_crtc base;
|
||||
|
@ -313,8 +313,8 @@ static const struct file_operations mtk_drm_fops = {
|
||||
* We need to override this because the device used to import the memory is
|
||||
* not dev->dev, as drm_gem_prime_import() expects.
|
||||
*/
|
||||
struct drm_gem_object *mtk_drm_gem_prime_import(struct drm_device *dev,
|
||||
struct dma_buf *dma_buf)
|
||||
static struct drm_gem_object *mtk_drm_gem_prime_import(struct drm_device *dev,
|
||||
struct dma_buf *dma_buf)
|
||||
{
|
||||
struct mtk_drm_private *private = dev->dev_private;
|
||||
|
||||
|
@ -389,15 +389,17 @@ static void meson_drv_unbind(struct device *dev)
|
||||
meson_canvas_free(priv->canvas, priv->canvas_id_vd1_2);
|
||||
}
|
||||
|
||||
drm_dev_unregister(drm);
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
drm_atomic_helper_shutdown(drm);
|
||||
component_unbind_all(dev, drm);
|
||||
drm_irq_uninstall(drm);
|
||||
drm_dev_put(drm);
|
||||
|
||||
if (priv->afbcd.ops) {
|
||||
priv->afbcd.ops->reset(priv);
|
||||
meson_rdma_free(priv);
|
||||
}
|
||||
|
||||
drm_dev_unregister(drm);
|
||||
drm_irq_uninstall(drm);
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
drm_dev_put(drm);
|
||||
}
|
||||
|
||||
static const struct component_master_ops meson_drv_master_ops = {
|
||||
|
@ -941,6 +941,11 @@ static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi)
|
||||
|
||||
}
|
||||
|
||||
static void meson_disable_regulator(void *data)
|
||||
{
|
||||
regulator_disable(data);
|
||||
}
|
||||
|
||||
static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
@ -989,6 +994,10 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
ret = regulator_enable(meson_dw_hdmi->hdmi_supply);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = devm_add_action_or_reset(dev, meson_disable_regulator,
|
||||
meson_dw_hdmi->hdmi_supply);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev,
|
||||
@ -1064,8 +1073,6 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
|
||||
DRM_DEBUG_DRIVER("encoder initialized\n");
|
||||
|
||||
meson_dw_hdmi_init(meson_dw_hdmi);
|
||||
|
||||
/* Bridge / Connector */
|
||||
|
||||
dw_plat_data->priv_data = meson_dw_hdmi;
|
||||
@ -1088,6 +1095,8 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
if (IS_ERR(meson_dw_hdmi->hdmi))
|
||||
return PTR_ERR(meson_dw_hdmi->hdmi);
|
||||
|
||||
meson_dw_hdmi_init(meson_dw_hdmi);
|
||||
|
||||
next_bridge = of_drm_find_bridge(pdev->dev.of_node);
|
||||
if (next_bridge)
|
||||
drm_bridge_attach(encoder, next_bridge,
|
||||
|
@ -131,7 +131,7 @@ enum {
|
||||
VID_PLL_DIV_15,
|
||||
};
|
||||
|
||||
void meson_vid_pll_set(struct meson_drm *priv, unsigned int div)
|
||||
static void meson_vid_pll_set(struct meson_drm *priv, unsigned int div)
|
||||
{
|
||||
unsigned int shift_val = 0;
|
||||
unsigned int shift_sel = 0;
|
||||
@ -487,9 +487,9 @@ static inline unsigned int pll_od_to_reg(unsigned int od)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
|
||||
unsigned int frac, unsigned int od1,
|
||||
unsigned int od2, unsigned int od3)
|
||||
static void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
|
||||
unsigned int frac, unsigned int od1,
|
||||
unsigned int od2, unsigned int od3)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
|
@ -890,8 +890,8 @@ bool meson_venc_hdmi_supported_vic(int vic)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic);
|
||||
|
||||
void meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode,
|
||||
union meson_hdmi_venc_mode *dmt_mode)
|
||||
static void meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode,
|
||||
union meson_hdmi_venc_mode *dmt_mode)
|
||||
{
|
||||
memset(dmt_mode, 0, sizeof(*dmt_mode));
|
||||
|
||||
|
@ -58,9 +58,10 @@ nvkm_firmware_load_blob(const struct nvkm_subdev *subdev, const char *base,
|
||||
|
||||
/**
|
||||
* nvkm_firmware_get - load firmware from the official nvidia/chip/ directory
|
||||
* @subdev subdevice that will use that firmware
|
||||
* @fwname name of firmware file to load
|
||||
* @fw firmware structure to load to
|
||||
* @subdev: subdevice that will use that firmware
|
||||
* @fwname: name of firmware file to load
|
||||
* @ver: firmware version to load
|
||||
* @fw: firmware structure to load to
|
||||
*
|
||||
* Use this function to load firmware files in the form nvidia/chip/fwname.bin.
|
||||
* Firmware files released by NVIDIA will always follow this format.
|
||||
@ -98,7 +99,7 @@ nvkm_firmware_get(const struct nvkm_subdev *subdev, const char *fwname, int ver,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* nvkm_firmware_put - release firmware loaded with nvkm_firmware_get
|
||||
*/
|
||||
void
|
||||
|
@ -889,6 +889,7 @@ static int omap_dmm_probe(struct platform_device *dev)
|
||||
&omap_dmm->refill_pa, GFP_KERNEL);
|
||||
if (!omap_dmm->refill_va) {
|
||||
dev_err(&dev->dev, "could not allocate refill memory\n");
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,15 @@ config DRM_PANEL
|
||||
menu "Display Panels"
|
||||
depends on DRM && DRM_PANEL
|
||||
|
||||
config DRM_PANEL_ABT_Y030XX067A
|
||||
tristate "ABT Y030XX067A 320x480 LCD panel"
|
||||
depends on OF && SPI
|
||||
select REGMAP_SPI
|
||||
help
|
||||
Say Y here to enable support for the Asia Better Technology Ltd.
|
||||
Y030XX067A 320x480 3.0" panel as found in the YLM RG-280M, RG-300
|
||||
and RG-99 handheld gaming consoles.
|
||||
|
||||
config DRM_PANEL_ARM_VERSATILE
|
||||
tristate "ARM Versatile panel driver"
|
||||
depends on OF
|
||||
@ -371,6 +380,18 @@ config DRM_PANEL_SAMSUNG_S6E8AA0
|
||||
select DRM_MIPI_DSI
|
||||
select VIDEOMODE_HELPERS
|
||||
|
||||
config DRM_PANEL_SAMSUNG_SOFEF00
|
||||
tristate "Samsung sofef00/s6e3fc2x01 OnePlus 6/6T DSI cmd mode panels"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select VIDEOMODE_HELPERS
|
||||
help
|
||||
Say Y or M here if you want to enable support for the Samsung AMOLED
|
||||
command mode panels found in the OnePlus 6/6T smartphones.
|
||||
|
||||
The panels are 2280x1080@60Hz and 2340x1080@60Hz respectively
|
||||
|
||||
config DRM_PANEL_SEIKO_43WVF1G
|
||||
tristate "Seiko 43WVF1G panel"
|
||||
depends on OF
|
||||
|
@ -1,4 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_DRM_PANEL_ABT_Y030XX067A) += panel-abt-y030xx067a.o
|
||||
obj-$(CONFIG_DRM_PANEL_ARM_VERSATILE) += panel-arm-versatile.o
|
||||
obj-$(CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596) += panel-asus-z00t-tm5p5-n35596.o
|
||||
obj-$(CONFIG_DRM_PANEL_BOE_HIMAX8279D) += panel-boe-himax8279d.o
|
||||
@ -39,6 +40,7 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0_SPI) += panel-samsung-s6e63m0-spi.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0_DSI) += panel-samsung-s6e63m0-dsi.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01) += panel-samsung-s6e88a0-ams452ef01.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o
|
||||
obj-$(CONFIG_DRM_PANEL_SAMSUNG_SOFEF00) += panel-samsung-sofef00.o
|
||||
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_LS037V7DW01) += panel-sharp-ls037v7dw01.o
|
||||
|
363
drivers/gpu/drm/panel/panel-abt-y030xx067a.c
Normal file
363
drivers/gpu/drm/panel/panel-abt-y030xx067a.c
Normal file
@ -0,0 +1,363 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Asia Better Technology Ltd. Y030XX067A IPS LCD panel driver
|
||||
*
|
||||
* Copyright (C) 2020, Paul Cercueil <paul@crapouillou.net>
|
||||
* Copyright (C) 2020, Christophe Branchereau <cbranchereau@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/media-bus-format.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
#define REG00_VBRT_CTRL(val) (val)
|
||||
|
||||
#define REG01_COM_DC(val) (val)
|
||||
|
||||
#define REG02_DA_CONTRAST(val) (val)
|
||||
#define REG02_VESA_SEL(val) ((val) << 5)
|
||||
#define REG02_COMDC_SW BIT(7)
|
||||
|
||||
#define REG03_VPOSITION(val) (val)
|
||||
#define REG03_BSMOUNT BIT(5)
|
||||
#define REG03_COMTST BIT(6)
|
||||
#define REG03_HPOSITION1 BIT(7)
|
||||
|
||||
#define REG04_HPOSITION1(val) (val)
|
||||
|
||||
#define REG05_CLIP BIT(0)
|
||||
#define REG05_NVM_VREFRESH BIT(1)
|
||||
#define REG05_SLFR BIT(2)
|
||||
#define REG05_SLBRCHARGE(val) ((val) << 3)
|
||||
#define REG05_PRECHARGE_LEVEL(val) ((val) << 6)
|
||||
|
||||
#define REG06_TEST5 BIT(0)
|
||||
#define REG06_SLDWN BIT(1)
|
||||
#define REG06_SLRGT BIT(2)
|
||||
#define REG06_TEST2 BIT(3)
|
||||
#define REG06_XPSAVE BIT(4)
|
||||
#define REG06_GAMMA_SEL(val) ((val) << 5)
|
||||
#define REG06_NT BIT(7)
|
||||
|
||||
#define REG07_TEST1 BIT(0)
|
||||
#define REG07_HDVD_POL BIT(1)
|
||||
#define REG07_CK_POL BIT(2)
|
||||
#define REG07_TEST3 BIT(3)
|
||||
#define REG07_TEST4 BIT(4)
|
||||
#define REG07_480_LINEMASK BIT(5)
|
||||
#define REG07_AMPTST(val) ((val) << 6)
|
||||
|
||||
#define REG08_SLHRC(val) (val)
|
||||
#define REG08_CLOCK_DIV(val) ((val) << 2)
|
||||
#define REG08_PANEL(val) ((val) << 5)
|
||||
|
||||
#define REG09_SUB_BRIGHT_R(val) (val)
|
||||
#define REG09_NW_NB BIT(6)
|
||||
#define REG09_IPCON BIT(7)
|
||||
|
||||
#define REG0A_SUB_BRIGHT_B(val) (val)
|
||||
#define REG0A_PAIR BIT(6)
|
||||
#define REG0A_DE_SEL BIT(7)
|
||||
|
||||
#define REG0B_MBK_POSITION(val) (val)
|
||||
#define REG0B_HD_FREERUN BIT(4)
|
||||
#define REG0B_VD_FREERUN BIT(5)
|
||||
#define REG0B_YUV2BIN(val) ((val) << 6)
|
||||
|
||||
#define REG0C_CONTRAST_R(val) (val)
|
||||
#define REG0C_DOUBLEREAD BIT(7)
|
||||
|
||||
#define REG0D_CONTRAST_G(val) (val)
|
||||
#define REG0D_RGB_YUV BIT(7)
|
||||
|
||||
#define REG0E_CONTRAST_B(val) (val)
|
||||
#define REG0E_PIXELCOLORDRIVE BIT(7)
|
||||
|
||||
#define REG0F_ASPECT BIT(0)
|
||||
#define REG0F_OVERSCAN(val) ((val) << 1)
|
||||
#define REG0F_FRAMEWIDTH(val) ((val) << 3)
|
||||
|
||||
#define REG10_BRIGHT(val) (val)
|
||||
|
||||
#define REG11_SIG_GAIN(val) (val)
|
||||
#define REG11_SIGC_CNTL BIT(6)
|
||||
#define REG11_SIGC_POL BIT(7)
|
||||
|
||||
#define REG12_COLOR(val) (val)
|
||||
#define REG12_PWCKSEL(val) ((val) << 6)
|
||||
|
||||
#define REG13_4096LEVEL_CNTL(val) (val)
|
||||
#define REG13_SL4096(val) ((val) << 4)
|
||||
#define REG13_LIMITER_CONTROL BIT(7)
|
||||
|
||||
#define REG14_PANEL_TEST(val) (val)
|
||||
|
||||
#define REG15_NVM_LINK0 BIT(0)
|
||||
#define REG15_NVM_LINK1 BIT(1)
|
||||
#define REG15_NVM_LINK2 BIT(2)
|
||||
#define REG15_NVM_LINK3 BIT(3)
|
||||
#define REG15_NVM_LINK4 BIT(4)
|
||||
#define REG15_NVM_LINK5 BIT(5)
|
||||
#define REG15_NVM_LINK6 BIT(6)
|
||||
#define REG15_NVM_LINK7 BIT(7)
|
||||
|
||||
struct y030xx067a_info {
|
||||
const struct drm_display_mode *display_modes;
|
||||
unsigned int num_modes;
|
||||
u16 width_mm, height_mm;
|
||||
u32 bus_format, bus_flags;
|
||||
};
|
||||
|
||||
struct y030xx067a {
|
||||
struct drm_panel panel;
|
||||
struct spi_device *spi;
|
||||
struct regmap *map;
|
||||
|
||||
const struct y030xx067a_info *panel_info;
|
||||
|
||||
struct regulator *supply;
|
||||
struct gpio_desc *reset_gpio;
|
||||
};
|
||||
|
||||
static inline struct y030xx067a *to_y030xx067a(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct y030xx067a, panel);
|
||||
}
|
||||
|
||||
static const struct reg_sequence y030xx067a_init_sequence[] = {
|
||||
{ 0x00, REG00_VBRT_CTRL(0x7f) },
|
||||
{ 0x01, REG01_COM_DC(0x3c) },
|
||||
{ 0x02, REG02_VESA_SEL(0x3) | REG02_DA_CONTRAST(0x1f) },
|
||||
{ 0x03, REG03_VPOSITION(0x0a) },
|
||||
{ 0x04, REG04_HPOSITION1(0xd2) },
|
||||
{ 0x05, REG05_CLIP | REG05_NVM_VREFRESH | REG05_SLBRCHARGE(0x2) },
|
||||
{ 0x06, REG06_XPSAVE | REG06_NT },
|
||||
{ 0x07, 0 },
|
||||
{ 0x08, REG08_PANEL(0x1) | REG08_CLOCK_DIV(0x2) },
|
||||
{ 0x09, REG09_SUB_BRIGHT_R(0x20) },
|
||||
{ 0x0a, REG0A_SUB_BRIGHT_B(0x20) },
|
||||
{ 0x0b, REG0B_HD_FREERUN | REG0B_VD_FREERUN },
|
||||
{ 0x0c, REG0C_CONTRAST_R(0x10) },
|
||||
{ 0x0d, REG0D_CONTRAST_G(0x10) },
|
||||
{ 0x0e, REG0E_CONTRAST_B(0x10) },
|
||||
{ 0x0f, 0 },
|
||||
{ 0x10, REG10_BRIGHT(0x7f) },
|
||||
{ 0x11, REG11_SIGC_CNTL | REG11_SIG_GAIN(0x3f) },
|
||||
{ 0x12, REG12_COLOR(0x20) | REG12_PWCKSEL(0x1) },
|
||||
{ 0x13, REG13_4096LEVEL_CNTL(0x8) },
|
||||
{ 0x14, 0 },
|
||||
{ 0x15, 0 },
|
||||
};
|
||||
|
||||
static int y030xx067a_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct y030xx067a *priv = to_y030xx067a(panel);
|
||||
struct device *dev = &priv->spi->dev;
|
||||
int err;
|
||||
|
||||
err = regulator_enable(priv->supply);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to enable power supply: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Reset the chip */
|
||||
gpiod_set_value_cansleep(priv->reset_gpio, 1);
|
||||
usleep_range(1000, 20000);
|
||||
gpiod_set_value_cansleep(priv->reset_gpio, 0);
|
||||
usleep_range(1000, 20000);
|
||||
|
||||
err = regmap_multi_reg_write(priv->map, y030xx067a_init_sequence,
|
||||
ARRAY_SIZE(y030xx067a_init_sequence));
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to init registers: %d\n", err);
|
||||
goto err_disable_regulator;
|
||||
}
|
||||
|
||||
msleep(120);
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable_regulator:
|
||||
regulator_disable(priv->supply);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int y030xx067a_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct y030xx067a *priv = to_y030xx067a(panel);
|
||||
|
||||
gpiod_set_value_cansleep(priv->reset_gpio, 1);
|
||||
regulator_disable(priv->supply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int y030xx067a_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct y030xx067a *priv = to_y030xx067a(panel);
|
||||
const struct y030xx067a_info *panel_info = priv->panel_info;
|
||||
struct drm_display_mode *mode;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < panel_info->num_modes; i++) {
|
||||
mode = drm_mode_duplicate(connector->dev,
|
||||
&panel_info->display_modes[i]);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER;
|
||||
if (panel_info->num_modes == 1)
|
||||
mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
|
||||
drm_mode_probed_add(connector, mode);
|
||||
}
|
||||
|
||||
connector->display_info.bpc = 8;
|
||||
connector->display_info.width_mm = panel_info->width_mm;
|
||||
connector->display_info.height_mm = panel_info->height_mm;
|
||||
|
||||
drm_display_info_set_bus_formats(&connector->display_info,
|
||||
&panel_info->bus_format, 1);
|
||||
connector->display_info.bus_flags = panel_info->bus_flags;
|
||||
|
||||
return panel_info->num_modes;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs y030xx067a_funcs = {
|
||||
.prepare = y030xx067a_prepare,
|
||||
.unprepare = y030xx067a_unprepare,
|
||||
.get_modes = y030xx067a_get_modes,
|
||||
};
|
||||
|
||||
static const struct regmap_config y030xx067a_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0x15,
|
||||
};
|
||||
|
||||
static int y030xx067a_probe(struct spi_device *spi)
|
||||
{
|
||||
struct device *dev = &spi->dev;
|
||||
struct y030xx067a *priv;
|
||||
int err;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->spi = spi;
|
||||
spi_set_drvdata(spi, priv);
|
||||
|
||||
priv->map = devm_regmap_init_spi(spi, &y030xx067a_regmap_config);
|
||||
if (IS_ERR(priv->map)) {
|
||||
dev_err(dev, "Unable to init regmap\n");
|
||||
return PTR_ERR(priv->map);
|
||||
}
|
||||
|
||||
priv->panel_info = of_device_get_match_data(dev);
|
||||
if (!priv->panel_info)
|
||||
return -EINVAL;
|
||||
|
||||
priv->supply = devm_regulator_get(dev, "power");
|
||||
if (IS_ERR(priv->supply)) {
|
||||
dev_err(dev, "Failed to get power supply\n");
|
||||
return PTR_ERR(priv->supply);
|
||||
}
|
||||
|
||||
priv->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(priv->reset_gpio)) {
|
||||
dev_err(dev, "Failed to get reset GPIO\n");
|
||||
return PTR_ERR(priv->reset_gpio);
|
||||
}
|
||||
|
||||
drm_panel_init(&priv->panel, dev, &y030xx067a_funcs,
|
||||
DRM_MODE_CONNECTOR_DPI);
|
||||
|
||||
err = drm_panel_of_backlight(&priv->panel);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
drm_panel_add(&priv->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int y030xx067a_remove(struct spi_device *spi)
|
||||
{
|
||||
struct y030xx067a *priv = spi_get_drvdata(spi);
|
||||
|
||||
drm_panel_remove(&priv->panel);
|
||||
drm_panel_disable(&priv->panel);
|
||||
drm_panel_unprepare(&priv->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode y030xx067a_modes[] = {
|
||||
{ /* 60 Hz */
|
||||
.clock = 14400,
|
||||
.hdisplay = 320,
|
||||
.hsync_start = 320 + 10,
|
||||
.hsync_end = 320 + 10 + 37,
|
||||
.htotal = 320 + 10 + 37 + 33,
|
||||
.vdisplay = 480,
|
||||
.vsync_start = 480 + 84,
|
||||
.vsync_end = 480 + 84 + 20,
|
||||
.vtotal = 480 + 84 + 20 + 16,
|
||||
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
|
||||
},
|
||||
{ /* 50 Hz */
|
||||
.clock = 12000,
|
||||
.hdisplay = 320,
|
||||
.hsync_start = 320 + 10,
|
||||
.hsync_end = 320 + 10 + 37,
|
||||
.htotal = 320 + 10 + 37 + 33,
|
||||
.vdisplay = 480,
|
||||
.vsync_start = 480 + 84,
|
||||
.vsync_end = 480 + 84 + 20,
|
||||
.vtotal = 480 + 84 + 20 + 16,
|
||||
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct y030xx067a_info y030xx067a_info = {
|
||||
.display_modes = y030xx067a_modes,
|
||||
.num_modes = ARRAY_SIZE(y030xx067a_modes),
|
||||
.width_mm = 69,
|
||||
.height_mm = 51,
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_3X8_DELTA,
|
||||
.bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE | DRM_BUS_FLAG_DE_LOW,
|
||||
};
|
||||
|
||||
static const struct of_device_id y030xx067a_of_match[] = {
|
||||
{ .compatible = "abt,y030xx067a", .data = &y030xx067a_info },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, y030xx067a_of_match);
|
||||
|
||||
static struct spi_driver y030xx067a_driver = {
|
||||
.driver = {
|
||||
.name = "abt-y030xx067a",
|
||||
.of_match_table = y030xx067a_of_match,
|
||||
},
|
||||
.probe = y030xx067a_probe,
|
||||
.remove = y030xx067a_remove,
|
||||
};
|
||||
module_spi_driver(y030xx067a_driver);
|
||||
|
||||
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
|
||||
MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -13,28 +13,28 @@
|
||||
|
||||
static int s6e63m0_spi_dcs_read(struct device *dev, const u8 cmd, u8 *data)
|
||||
{
|
||||
/*
|
||||
* FIXME: implement reading DCS commands over SPI so we can
|
||||
* properly identify which physical panel is connected.
|
||||
*/
|
||||
*data = 0;
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
u16 buf[1];
|
||||
u16 rbuf[1];
|
||||
int ret;
|
||||
|
||||
return 0;
|
||||
/* SPI buffers are always in CPU order */
|
||||
buf[0] = (u16)cmd;
|
||||
ret = spi_write_then_read(spi, buf, 2, rbuf, 2);
|
||||
dev_dbg(dev, "READ CMD: %04x RET: %04x\n", buf[0], rbuf[0]);
|
||||
if (!ret)
|
||||
/* These high 8 bits of the 9 contains the readout */
|
||||
*data = (rbuf[0] & 0x1ff) >> 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int s6e63m0_spi_write_word(struct device *dev, u16 data)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
struct spi_transfer xfer = {
|
||||
.len = 2,
|
||||
.tx_buf = &data,
|
||||
};
|
||||
struct spi_message msg;
|
||||
|
||||
spi_message_init(&msg);
|
||||
spi_message_add_tail(&xfer, &msg);
|
||||
|
||||
return spi_sync(spi, &msg);
|
||||
/* SPI buffers are always in CPU order */
|
||||
return spi_write(spi, &data, 2);
|
||||
}
|
||||
|
||||
static int s6e63m0_spi_dcs_write(struct device *dev, const u8 *data, size_t len)
|
||||
@ -42,10 +42,17 @@ static int s6e63m0_spi_dcs_write(struct device *dev, const u8 *data, size_t len)
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(dev, "SPI writing dcs seq: %*ph\n", (int)len, data);
|
||||
|
||||
/*
|
||||
* This sends 9 bits with the first bit (bit 8) set to 0
|
||||
* This indicates that this is a command. Anything after the
|
||||
* command is data.
|
||||
*/
|
||||
ret = s6e63m0_spi_write_word(dev, *data);
|
||||
|
||||
while (!ret && --len) {
|
||||
++data;
|
||||
/* This sends 9 bits with the first bit (bit 8) set to 1 */
|
||||
ret = s6e63m0_spi_write_word(dev, *data | DATA_MASK);
|
||||
}
|
||||
|
||||
@ -65,7 +72,8 @@ static int s6e63m0_spi_probe(struct spi_device *spi)
|
||||
int ret;
|
||||
|
||||
spi->bits_per_word = 9;
|
||||
spi->mode = SPI_MODE_3;
|
||||
/* Preserve e.g. SPI_3WIRE setting */
|
||||
spi->mode |= SPI_MODE_3;
|
||||
ret = spi_setup(spi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "spi setup failed.\n");
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/media-bus-format.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
@ -410,6 +411,7 @@ static int s6e63m0_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &default_mode);
|
||||
if (!mode) {
|
||||
@ -419,6 +421,13 @@ static int s6e63m0_get_modes(struct drm_panel *panel,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
drm_display_info_set_bus_formats(&connector->display_info,
|
||||
&bus_format, 1);
|
||||
connector->display_info.bus_flags = DRM_BUS_FLAG_DE_LOW |
|
||||
DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
|
351
drivers/gpu/drm/panel/panel-samsung-sofef00.c
Normal file
351
drivers/gpu/drm/panel/panel-samsung-sofef00.c
Normal file
@ -0,0 +1,351 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2020 Caleb Connolly <caleb@connolly.tech>
|
||||
* Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
|
||||
* Copyright (c) 2020, 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/of_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/swab.h>
|
||||
#include <linux/backlight.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct sofef00_panel {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct regulator *supply;
|
||||
struct gpio_desc *reset_gpio;
|
||||
const struct drm_display_mode *mode;
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
static inline
|
||||
struct sofef00_panel *to_sofef00_panel(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct sofef00_panel, panel);
|
||||
}
|
||||
|
||||
#define dsi_dcs_write_seq(dsi, seq...) do { \
|
||||
static const u8 d[] = { seq }; \
|
||||
int ret; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
static void sofef00_panel_reset(struct sofef00_panel *ctx)
|
||||
{
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(5000, 6000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
usleep_range(2000, 3000);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
||||
usleep_range(12000, 13000);
|
||||
}
|
||||
|
||||
static int sofef00_panel_on(struct sofef00_panel *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_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set tear on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
|
||||
dsi_dcs_write_seq(dsi, 0xb0, 0x07);
|
||||
dsi_dcs_write_seq(dsi, 0xb6, 0x12);
|
||||
dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
|
||||
dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sofef00_panel_off(struct sofef00_panel *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;
|
||||
}
|
||||
msleep(40);
|
||||
|
||||
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(160);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sofef00_panel_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct sofef00_panel *ctx = to_sofef00_panel(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_enable(ctx->supply);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sofef00_panel_reset(ctx);
|
||||
|
||||
ret = sofef00_panel_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->prepared = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sofef00_panel_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct sofef00_panel *ctx = to_sofef00_panel(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (!ctx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = sofef00_panel_off(ctx);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
|
||||
|
||||
regulator_disable(ctx->supply);
|
||||
|
||||
ctx->prepared = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode enchilada_panel_mode = {
|
||||
.clock = (1080 + 112 + 16 + 36) * (2280 + 36 + 8 + 12) * 60 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 112,
|
||||
.hsync_end = 1080 + 112 + 16,
|
||||
.htotal = 1080 + 112 + 16 + 36,
|
||||
.vdisplay = 2280,
|
||||
.vsync_start = 2280 + 36,
|
||||
.vsync_end = 2280 + 36 + 8,
|
||||
.vtotal = 2280 + 36 + 8 + 12,
|
||||
.width_mm = 68,
|
||||
.height_mm = 145,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode fajita_panel_mode = {
|
||||
.clock = (1080 + 72 + 16 + 36) * (2340 + 32 + 4 + 18) * 60 / 1000,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 72,
|
||||
.hsync_end = 1080 + 72 + 16,
|
||||
.htotal = 1080 + 72 + 16 + 36,
|
||||
.vdisplay = 2340,
|
||||
.vsync_start = 2340 + 32,
|
||||
.vsync_end = 2340 + 32 + 4,
|
||||
.vtotal = 2340 + 32 + 4 + 18,
|
||||
.width_mm = 68,
|
||||
.height_mm = 145,
|
||||
};
|
||||
|
||||
static int sofef00_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
struct sofef00_panel *ctx = to_sofef00_panel(panel);
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, ctx->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 sofef00_panel_panel_funcs = {
|
||||
.prepare = sofef00_panel_prepare,
|
||||
.unprepare = sofef00_panel_unprepare,
|
||||
.get_modes = sofef00_panel_get_modes,
|
||||
};
|
||||
|
||||
static int sofef00_panel_bl_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = bl_get_data(bl);
|
||||
int err;
|
||||
u16 brightness;
|
||||
|
||||
brightness = (u16)backlight_get_brightness(bl);
|
||||
// This panel needs the high and low bytes swapped for the brightness value
|
||||
brightness = __swab16(brightness);
|
||||
|
||||
err = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct backlight_ops sofef00_panel_bl_ops = {
|
||||
.update_status = sofef00_panel_bl_update_status,
|
||||
};
|
||||
|
||||
static struct backlight_device *
|
||||
sofef00_create_backlight(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
const struct backlight_properties props = {
|
||||
.type = BACKLIGHT_PLATFORM,
|
||||
.brightness = 1023,
|
||||
.max_brightness = 1023,
|
||||
};
|
||||
|
||||
return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
|
||||
&sofef00_panel_bl_ops, &props);
|
||||
}
|
||||
|
||||
static int sofef00_panel_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct sofef00_panel *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->mode = of_device_get_match_data(dev);
|
||||
|
||||
if (!ctx->mode) {
|
||||
dev_err(dev, "Missing device mode\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ctx->supply = devm_regulator_get(dev, "vddio");
|
||||
if (IS_ERR(ctx->supply)) {
|
||||
ret = PTR_ERR(ctx->supply);
|
||||
dev_err(dev, "Failed to get vddio regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(ctx->reset_gpio)) {
|
||||
ret = PTR_ERR(ctx->reset_gpio);
|
||||
dev_warn(dev, "Failed to get reset-gpios: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->dsi = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &sofef00_panel_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ctx->panel.backlight = sofef00_create_backlight(dsi);
|
||||
if (IS_ERR(ctx->panel.backlight))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
|
||||
"Failed to create 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);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sofef00_panel_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct sofef00_panel *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 sofef00_panel_of_match[] = {
|
||||
{ // OnePlus 6 / enchilada
|
||||
.compatible = "samsung,sofef00",
|
||||
.data = &enchilada_panel_mode,
|
||||
},
|
||||
{ // OnePlus 6T / fajita
|
||||
.compatible = "samsung,s6e3fc2x01",
|
||||
.data = &fajita_panel_mode,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sofef00_panel_of_match);
|
||||
|
||||
static struct mipi_dsi_driver sofef00_panel_driver = {
|
||||
.probe = sofef00_panel_probe,
|
||||
.remove = sofef00_panel_remove,
|
||||
.driver = {
|
||||
.name = "panel-oneplus6",
|
||||
.of_match_table = sofef00_panel_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_mipi_dsi_driver(sofef00_panel_driver);
|
||||
|
||||
MODULE_AUTHOR("Caleb Connolly <caleb@connolly.tech>");
|
||||
MODULE_DESCRIPTION("DRM driver for Samsung AMOLED DSI panels found in OnePlus 6/6T phones");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -76,7 +76,7 @@ struct tpg110 {
|
||||
*/
|
||||
struct drm_panel panel;
|
||||
/**
|
||||
* @panel_type: the panel mode as detected
|
||||
* @panel_mode: the panel mode as detected
|
||||
*/
|
||||
const struct tpg110_panel_mode *panel_mode;
|
||||
/**
|
||||
@ -362,6 +362,7 @@ static int tpg110_enable(struct drm_panel *panel)
|
||||
/**
|
||||
* tpg110_get_modes() - return the appropriate mode
|
||||
* @panel: the panel to get the mode for
|
||||
* @connector: reference to the central DRM connector control structure
|
||||
*
|
||||
* This currently does not present a forest of modes, instead it
|
||||
* presents the mode that is configured for the system under use,
|
||||
|
@ -200,7 +200,6 @@ int panfrost_device_init(struct panfrost_device *pfdev)
|
||||
struct resource *res;
|
||||
|
||||
mutex_init(&pfdev->sched_lock);
|
||||
mutex_init(&pfdev->reset_lock);
|
||||
INIT_LIST_HEAD(&pfdev->scheduled_jobs);
|
||||
INIT_LIST_HEAD(&pfdev->as_lru_list);
|
||||
|
||||
|
@ -106,7 +106,11 @@ struct panfrost_device {
|
||||
struct panfrost_perfcnt *perfcnt;
|
||||
|
||||
struct mutex sched_lock;
|
||||
struct mutex reset_lock;
|
||||
|
||||
struct {
|
||||
struct work_struct work;
|
||||
atomic_t pending;
|
||||
} reset;
|
||||
|
||||
struct mutex shrinker_lock;
|
||||
struct list_head shrinker_list;
|
||||
|
@ -20,12 +20,21 @@
|
||||
#include "panfrost_gpu.h"
|
||||
#include "panfrost_mmu.h"
|
||||
|
||||
#define JOB_TIMEOUT_MS 500
|
||||
|
||||
#define job_write(dev, reg, data) writel(data, dev->iomem + (reg))
|
||||
#define job_read(dev, reg) readl(dev->iomem + (reg))
|
||||
|
||||
enum panfrost_queue_status {
|
||||
PANFROST_QUEUE_STATUS_ACTIVE,
|
||||
PANFROST_QUEUE_STATUS_STOPPED,
|
||||
PANFROST_QUEUE_STATUS_STARTING,
|
||||
PANFROST_QUEUE_STATUS_FAULT_PENDING,
|
||||
};
|
||||
|
||||
struct panfrost_queue_state {
|
||||
struct drm_gpu_scheduler sched;
|
||||
bool stopped;
|
||||
atomic_t status;
|
||||
struct mutex lock;
|
||||
u64 fence_context;
|
||||
u64 emit_seqno;
|
||||
@ -373,28 +382,61 @@ void panfrost_job_enable_interrupts(struct panfrost_device *pfdev)
|
||||
static bool panfrost_scheduler_stop(struct panfrost_queue_state *queue,
|
||||
struct drm_sched_job *bad)
|
||||
{
|
||||
enum panfrost_queue_status old_status;
|
||||
bool stopped = false;
|
||||
|
||||
mutex_lock(&queue->lock);
|
||||
if (!queue->stopped) {
|
||||
drm_sched_stop(&queue->sched, bad);
|
||||
if (bad)
|
||||
drm_sched_increase_karma(bad);
|
||||
queue->stopped = true;
|
||||
stopped = true;
|
||||
}
|
||||
old_status = atomic_xchg(&queue->status,
|
||||
PANFROST_QUEUE_STATUS_STOPPED);
|
||||
if (old_status == PANFROST_QUEUE_STATUS_STOPPED)
|
||||
goto out;
|
||||
|
||||
WARN_ON(old_status != PANFROST_QUEUE_STATUS_ACTIVE);
|
||||
drm_sched_stop(&queue->sched, bad);
|
||||
if (bad)
|
||||
drm_sched_increase_karma(bad);
|
||||
|
||||
stopped = true;
|
||||
|
||||
/*
|
||||
* Set the timeout to max so the timer doesn't get started
|
||||
* when we return from the timeout handler (restored in
|
||||
* panfrost_scheduler_start()).
|
||||
*/
|
||||
queue->sched.timeout = MAX_SCHEDULE_TIMEOUT;
|
||||
|
||||
out:
|
||||
mutex_unlock(&queue->lock);
|
||||
|
||||
return stopped;
|
||||
}
|
||||
|
||||
static void panfrost_scheduler_start(struct panfrost_queue_state *queue)
|
||||
{
|
||||
enum panfrost_queue_status old_status;
|
||||
|
||||
mutex_lock(&queue->lock);
|
||||
old_status = atomic_xchg(&queue->status,
|
||||
PANFROST_QUEUE_STATUS_STARTING);
|
||||
WARN_ON(old_status != PANFROST_QUEUE_STATUS_STOPPED);
|
||||
|
||||
/* Restore the original timeout before starting the scheduler. */
|
||||
queue->sched.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS);
|
||||
drm_sched_resubmit_jobs(&queue->sched);
|
||||
drm_sched_start(&queue->sched, true);
|
||||
old_status = atomic_xchg(&queue->status,
|
||||
PANFROST_QUEUE_STATUS_ACTIVE);
|
||||
if (old_status == PANFROST_QUEUE_STATUS_FAULT_PENDING)
|
||||
drm_sched_fault(&queue->sched);
|
||||
|
||||
mutex_unlock(&queue->lock);
|
||||
}
|
||||
|
||||
static void panfrost_job_timedout(struct drm_sched_job *sched_job)
|
||||
{
|
||||
struct panfrost_job *job = to_panfrost_job(sched_job);
|
||||
struct panfrost_device *pfdev = job->pfdev;
|
||||
int js = panfrost_job_get_slot(job);
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* If the GPU managed to complete this jobs fence, the timeout is
|
||||
@ -415,56 +457,9 @@ static void panfrost_job_timedout(struct drm_sched_job *sched_job)
|
||||
if (!panfrost_scheduler_stop(&pfdev->js->queue[js], sched_job))
|
||||
return;
|
||||
|
||||
if (!mutex_trylock(&pfdev->reset_lock))
|
||||
return;
|
||||
|
||||
for (i = 0; i < NUM_JOB_SLOTS; i++) {
|
||||
struct drm_gpu_scheduler *sched = &pfdev->js->queue[i].sched;
|
||||
|
||||
/*
|
||||
* If the queue is still active, make sure we wait for any
|
||||
* pending timeouts.
|
||||
*/
|
||||
if (!pfdev->js->queue[i].stopped)
|
||||
cancel_delayed_work_sync(&sched->work_tdr);
|
||||
|
||||
/*
|
||||
* If the scheduler was not already stopped, there's a tiny
|
||||
* chance a timeout has expired just before we stopped it, and
|
||||
* drm_sched_stop() does not flush pending works. Let's flush
|
||||
* them now so the timeout handler doesn't get called in the
|
||||
* middle of a reset.
|
||||
*/
|
||||
if (panfrost_scheduler_stop(&pfdev->js->queue[i], NULL))
|
||||
cancel_delayed_work_sync(&sched->work_tdr);
|
||||
|
||||
/*
|
||||
* Now that we cancelled the pending timeouts, we can safely
|
||||
* reset the stopped state.
|
||||
*/
|
||||
pfdev->js->queue[i].stopped = false;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&pfdev->js->job_lock, flags);
|
||||
for (i = 0; i < NUM_JOB_SLOTS; i++) {
|
||||
if (pfdev->jobs[i]) {
|
||||
pm_runtime_put_noidle(pfdev->dev);
|
||||
panfrost_devfreq_record_idle(&pfdev->pfdevfreq);
|
||||
pfdev->jobs[i] = NULL;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&pfdev->js->job_lock, flags);
|
||||
|
||||
panfrost_device_reset(pfdev);
|
||||
|
||||
for (i = 0; i < NUM_JOB_SLOTS; i++)
|
||||
drm_sched_resubmit_jobs(&pfdev->js->queue[i].sched);
|
||||
|
||||
mutex_unlock(&pfdev->reset_lock);
|
||||
|
||||
/* restart scheduler after GPU is usable again */
|
||||
for (i = 0; i < NUM_JOB_SLOTS; i++)
|
||||
drm_sched_start(&pfdev->js->queue[i].sched, true);
|
||||
/* Schedule a reset if there's no reset in progress. */
|
||||
if (!atomic_xchg(&pfdev->reset.pending, 1))
|
||||
schedule_work(&pfdev->reset.work);
|
||||
}
|
||||
|
||||
static const struct drm_sched_backend_ops panfrost_sched_ops = {
|
||||
@ -496,6 +491,8 @@ static irqreturn_t panfrost_job_irq_handler(int irq, void *data)
|
||||
job_write(pfdev, JOB_INT_CLEAR, mask);
|
||||
|
||||
if (status & JOB_INT_MASK_ERR(j)) {
|
||||
enum panfrost_queue_status old_status;
|
||||
|
||||
job_write(pfdev, JS_COMMAND_NEXT(j), JS_COMMAND_NOP);
|
||||
|
||||
dev_err(pfdev->dev, "js fault, js=%d, status=%s, head=0x%x, tail=0x%x",
|
||||
@ -504,7 +501,18 @@ static irqreturn_t panfrost_job_irq_handler(int irq, void *data)
|
||||
job_read(pfdev, JS_HEAD_LO(j)),
|
||||
job_read(pfdev, JS_TAIL_LO(j)));
|
||||
|
||||
drm_sched_fault(&pfdev->js->queue[j].sched);
|
||||
/*
|
||||
* When the queue is being restarted we don't report
|
||||
* faults directly to avoid races between the timeout
|
||||
* and reset handlers. panfrost_scheduler_start() will
|
||||
* call drm_sched_fault() after the queue has been
|
||||
* started if status == FAULT_PENDING.
|
||||
*/
|
||||
old_status = atomic_cmpxchg(&pfdev->js->queue[j].status,
|
||||
PANFROST_QUEUE_STATUS_STARTING,
|
||||
PANFROST_QUEUE_STATUS_FAULT_PENDING);
|
||||
if (old_status == PANFROST_QUEUE_STATUS_ACTIVE)
|
||||
drm_sched_fault(&pfdev->js->queue[j].sched);
|
||||
}
|
||||
|
||||
if (status & JOB_INT_MASK_DONE(j)) {
|
||||
@ -531,11 +539,66 @@ static irqreturn_t panfrost_job_irq_handler(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void panfrost_reset(struct work_struct *work)
|
||||
{
|
||||
struct panfrost_device *pfdev = container_of(work,
|
||||
struct panfrost_device,
|
||||
reset.work);
|
||||
unsigned long flags;
|
||||
unsigned int i;
|
||||
bool cookie;
|
||||
|
||||
cookie = dma_fence_begin_signalling();
|
||||
for (i = 0; i < NUM_JOB_SLOTS; i++) {
|
||||
/*
|
||||
* We want pending timeouts to be handled before we attempt
|
||||
* to stop the scheduler. If we don't do that and the timeout
|
||||
* handler is in flight, it might have removed the bad job
|
||||
* from the list, and we'll lose this job if the reset handler
|
||||
* enters the critical section in panfrost_scheduler_stop()
|
||||
* before the timeout handler.
|
||||
*
|
||||
* Timeout is set to MAX_SCHEDULE_TIMEOUT - 1 because we need
|
||||
* something big enough to make sure the timer will not expire
|
||||
* before we manage to stop the scheduler, but we can't use
|
||||
* MAX_SCHEDULE_TIMEOUT because drm_sched_get_cleanup_job()
|
||||
* considers that as 'timer is not running' and will dequeue
|
||||
* the job without making sure the timeout handler is not
|
||||
* running.
|
||||
*/
|
||||
pfdev->js->queue[i].sched.timeout = MAX_SCHEDULE_TIMEOUT - 1;
|
||||
cancel_delayed_work_sync(&pfdev->js->queue[i].sched.work_tdr);
|
||||
panfrost_scheduler_stop(&pfdev->js->queue[i], NULL);
|
||||
}
|
||||
|
||||
/* All timers have been stopped, we can safely reset the pending state. */
|
||||
atomic_set(&pfdev->reset.pending, 0);
|
||||
|
||||
spin_lock_irqsave(&pfdev->js->job_lock, flags);
|
||||
for (i = 0; i < NUM_JOB_SLOTS; i++) {
|
||||
if (pfdev->jobs[i]) {
|
||||
pm_runtime_put_noidle(pfdev->dev);
|
||||
panfrost_devfreq_record_idle(&pfdev->pfdevfreq);
|
||||
pfdev->jobs[i] = NULL;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&pfdev->js->job_lock, flags);
|
||||
|
||||
panfrost_device_reset(pfdev);
|
||||
|
||||
for (i = 0; i < NUM_JOB_SLOTS; i++)
|
||||
panfrost_scheduler_start(&pfdev->js->queue[i]);
|
||||
|
||||
dma_fence_end_signalling(cookie);
|
||||
}
|
||||
|
||||
int panfrost_job_init(struct panfrost_device *pfdev)
|
||||
{
|
||||
struct panfrost_job_slot *js;
|
||||
int ret, j, irq;
|
||||
|
||||
INIT_WORK(&pfdev->reset.work, panfrost_reset);
|
||||
|
||||
pfdev->js = js = devm_kzalloc(pfdev->dev, sizeof(*js), GFP_KERNEL);
|
||||
if (!js)
|
||||
return -ENOMEM;
|
||||
@ -560,7 +623,7 @@ int panfrost_job_init(struct panfrost_device *pfdev)
|
||||
|
||||
ret = drm_sched_init(&js->queue[j].sched,
|
||||
&panfrost_sched_ops,
|
||||
1, 0, msecs_to_jiffies(500),
|
||||
1, 0, msecs_to_jiffies(JOB_TIMEOUT_MS),
|
||||
"pan_js");
|
||||
if (ret) {
|
||||
dev_err(pfdev->dev, "Failed to create scheduler: %d.", ret);
|
||||
|
@ -30,7 +30,7 @@ static const struct {
|
||||
REGDEF(CLCD_PL111_LCUR),
|
||||
};
|
||||
|
||||
int pl111_debugfs_regs(struct seq_file *m, void *unused)
|
||||
static int pl111_debugfs_regs(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
|
@ -353,7 +353,7 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe,
|
||||
drm_crtc_vblank_on(crtc);
|
||||
}
|
||||
|
||||
void pl111_display_disable(struct drm_simple_display_pipe *pipe)
|
||||
static void pl111_display_disable(struct drm_simple_display_pipe *pipe)
|
||||
{
|
||||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct drm_device *drm = crtc->dev;
|
||||
|
@ -169,20 +169,6 @@ struct qxl_drm_image {
|
||||
struct list_head chunk_list;
|
||||
};
|
||||
|
||||
struct qxl_fb_image {
|
||||
struct qxl_device *qdev;
|
||||
uint32_t pseudo_palette[16];
|
||||
struct fb_image fb_image;
|
||||
uint32_t visual;
|
||||
};
|
||||
|
||||
struct qxl_draw_fill {
|
||||
struct qxl_device *qdev;
|
||||
struct qxl_rect rect;
|
||||
uint32_t color;
|
||||
uint16_t rop;
|
||||
};
|
||||
|
||||
/*
|
||||
* Debugfs
|
||||
*/
|
||||
@ -191,8 +177,6 @@ struct qxl_debugfs {
|
||||
unsigned int num_files;
|
||||
};
|
||||
|
||||
int qxl_debugfs_fence_init(struct qxl_device *rdev);
|
||||
|
||||
struct qxl_device {
|
||||
struct drm_device ddev;
|
||||
|
||||
@ -274,6 +258,8 @@ struct qxl_device {
|
||||
|
||||
#define to_qxl(dev) container_of(dev, struct qxl_device, ddev)
|
||||
|
||||
int qxl_debugfs_fence_init(struct qxl_device *rdev);
|
||||
|
||||
extern const struct drm_ioctl_desc qxl_ioctls[];
|
||||
extern int qxl_max_ioctl;
|
||||
|
||||
|
@ -350,7 +350,7 @@ static void dw_mipi_dsi_phy_write(struct dw_mipi_dsi_rockchip *dsi,
|
||||
dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* ns2bc - Nanoseconds to byte clock cycles
|
||||
*/
|
||||
static inline unsigned int ns2bc(struct dw_mipi_dsi_rockchip *dsi, int ns)
|
||||
@ -358,7 +358,7 @@ static inline unsigned int ns2bc(struct dw_mipi_dsi_rockchip *dsi, int ns)
|
||||
return DIV_ROUND_UP(ns * dsi->lane_mbps / 8, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* ns2ui - Nanoseconds to UI time periods
|
||||
*/
|
||||
static inline unsigned int ns2ui(struct dw_mipi_dsi_rockchip *dsi, int ns)
|
||||
|
@ -42,7 +42,7 @@ struct rockchip_lvds;
|
||||
container_of(c, struct rockchip_lvds, encoder)
|
||||
|
||||
/**
|
||||
* rockchip_lvds_soc_data - rockchip lvds Soc private data
|
||||
* struct rockchip_lvds_soc_data - rockchip lvds Soc private data
|
||||
* @probe: LVDS platform probe function
|
||||
* @helper_funcs: LVDS connector helper functions
|
||||
*/
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_vop.h"
|
||||
#include "rockchip_rgb.h"
|
||||
|
||||
#define encoder_to_rgb(c) container_of(c, struct rockchip_rgb, encoder)
|
||||
|
||||
|
@ -573,19 +573,12 @@ int savage_driver_firstopen(struct drm_device *dev)
|
||||
{
|
||||
drm_savage_private_t *dev_priv = dev->dev_private;
|
||||
unsigned long mmio_base, fb_base, fb_size, aperture_base;
|
||||
/* fb_rsrc and aper_rsrc aren't really used currently, but still exist
|
||||
* in case we decide we need information on the BAR for BSD in the
|
||||
* future.
|
||||
*/
|
||||
unsigned int fb_rsrc, aper_rsrc;
|
||||
int ret = 0;
|
||||
|
||||
if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
|
||||
fb_rsrc = 0;
|
||||
fb_base = pci_resource_start(dev->pdev, 0);
|
||||
fb_size = SAVAGE_FB_SIZE_S3;
|
||||
mmio_base = fb_base + SAVAGE_FB_SIZE_S3;
|
||||
aper_rsrc = 0;
|
||||
aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
|
||||
/* this should always be true */
|
||||
if (pci_resource_len(dev->pdev, 0) == 0x08000000) {
|
||||
@ -607,10 +600,8 @@ int savage_driver_firstopen(struct drm_device *dev)
|
||||
} else if (dev_priv->chipset != S3_SUPERSAVAGE &&
|
||||
dev_priv->chipset != S3_SAVAGE2000) {
|
||||
mmio_base = pci_resource_start(dev->pdev, 0);
|
||||
fb_rsrc = 1;
|
||||
fb_base = pci_resource_start(dev->pdev, 1);
|
||||
fb_size = SAVAGE_FB_SIZE_S4;
|
||||
aper_rsrc = 1;
|
||||
aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
|
||||
/* this should always be true */
|
||||
if (pci_resource_len(dev->pdev, 1) == 0x08000000) {
|
||||
@ -626,10 +617,8 @@ int savage_driver_firstopen(struct drm_device *dev)
|
||||
}
|
||||
} else {
|
||||
mmio_base = pci_resource_start(dev->pdev, 0);
|
||||
fb_rsrc = 1;
|
||||
fb_base = pci_resource_start(dev->pdev, 1);
|
||||
fb_size = pci_resource_len(dev->pdev, 1);
|
||||
aper_rsrc = 2;
|
||||
aperture_base = pci_resource_start(dev->pdev, 2);
|
||||
/* Automatic MTRR setup will do the right thing. */
|
||||
}
|
||||
|
@ -446,7 +446,7 @@ void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad)
|
||||
EXPORT_SYMBOL(drm_sched_stop);
|
||||
|
||||
/**
|
||||
* drm_sched_job_recovery - recover jobs after a reset
|
||||
* drm_sched_start - recover jobs after a reset
|
||||
*
|
||||
* @sched: scheduler instance
|
||||
* @full_recovery: proceed with complete sched restart
|
||||
|
@ -120,44 +120,58 @@ sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,
|
||||
static bool
|
||||
sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in)
|
||||
{
|
||||
struct drm_dp_sideband_msg_req_body out = {0};
|
||||
struct drm_dp_sideband_msg_req_body *out;
|
||||
struct drm_printer p = drm_err_printer(PREFIX_STR);
|
||||
struct drm_dp_sideband_msg_tx txmsg;
|
||||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
int i, ret;
|
||||
bool result = true;
|
||||
|
||||
drm_dp_encode_sideband_req(in, &txmsg);
|
||||
ret = drm_dp_decode_sideband_req(&txmsg, &out);
|
||||
out = kzalloc(sizeof(*out), GFP_KERNEL);
|
||||
if (!out)
|
||||
return false;
|
||||
|
||||
txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
|
||||
if (!txmsg)
|
||||
return false;
|
||||
|
||||
drm_dp_encode_sideband_req(in, txmsg);
|
||||
ret = drm_dp_decode_sideband_req(txmsg, out);
|
||||
if (ret < 0) {
|
||||
drm_printf(&p, "Failed to decode sideband request: %d\n",
|
||||
ret);
|
||||
return false;
|
||||
result = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!sideband_msg_req_equal(in, &out)) {
|
||||
if (!sideband_msg_req_equal(in, out)) {
|
||||
drm_printf(&p, "Encode/decode failed, expected:\n");
|
||||
drm_dp_dump_sideband_msg_req_body(in, 1, &p);
|
||||
drm_printf(&p, "Got:\n");
|
||||
drm_dp_dump_sideband_msg_req_body(&out, 1, &p);
|
||||
return false;
|
||||
drm_dp_dump_sideband_msg_req_body(out, 1, &p);
|
||||
result = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (in->req_type) {
|
||||
case DP_REMOTE_DPCD_WRITE:
|
||||
kfree(out.u.dpcd_write.bytes);
|
||||
kfree(out->u.dpcd_write.bytes);
|
||||
break;
|
||||
case DP_REMOTE_I2C_READ:
|
||||
for (i = 0; i < out.u.i2c_read.num_transactions; i++)
|
||||
kfree(out.u.i2c_read.transactions[i].bytes);
|
||||
for (i = 0; i < out->u.i2c_read.num_transactions; i++)
|
||||
kfree(out->u.i2c_read.transactions[i].bytes);
|
||||
break;
|
||||
case DP_REMOTE_I2C_WRITE:
|
||||
kfree(out.u.i2c_write.bytes);
|
||||
kfree(out->u.i2c_write.bytes);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Clear everything but the req_type for the input */
|
||||
memset(&in->u, 0, sizeof(in->u));
|
||||
|
||||
return true;
|
||||
out:
|
||||
kfree(out);
|
||||
kfree(txmsg);
|
||||
return result;
|
||||
}
|
||||
|
||||
int igt_dp_mst_sideband_msg_req_decode(void *unused)
|
||||
|
@ -330,10 +330,9 @@ static struct drm_device mock_drm_device = {
|
||||
static int execute_drm_mode_fb_cmd2(struct drm_mode_fb_cmd2 *r)
|
||||
{
|
||||
int buffer_created = 0;
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
mock_drm_device.dev_private = &buffer_created;
|
||||
fb = drm_internal_framebuffer_create(&mock_drm_device, r, NULL);
|
||||
drm_internal_framebuffer_create(&mock_drm_device, r, NULL);
|
||||
return buffer_created;
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ static int igt_sanitycheck(void *ignored)
|
||||
static bool assert_no_holes(const struct drm_mm *mm)
|
||||
{
|
||||
struct drm_mm_node *hole;
|
||||
u64 hole_start, hole_end;
|
||||
u64 hole_start, __always_unused hole_end;
|
||||
unsigned long count;
|
||||
|
||||
count = 0;
|
||||
|
@ -167,6 +167,12 @@ struct sti_hdmi_connector {
|
||||
#define to_sti_hdmi_connector(x) \
|
||||
container_of(x, struct sti_hdmi_connector, drm_connector)
|
||||
|
||||
static const struct drm_prop_enum_list colorspace_mode_names[] = {
|
||||
{ HDMI_COLORSPACE_RGB, "rgb" },
|
||||
{ HDMI_COLORSPACE_YUV422, "yuv422" },
|
||||
{ HDMI_COLORSPACE_YUV444, "yuv444" },
|
||||
};
|
||||
|
||||
u32 hdmi_read(struct sti_hdmi *hdmi, int offset)
|
||||
{
|
||||
return readl(hdmi->regs + offset);
|
||||
|
@ -33,12 +33,6 @@ struct hdmi_audio_params {
|
||||
struct hdmi_audio_infoframe cea;
|
||||
};
|
||||
|
||||
static const struct drm_prop_enum_list colorspace_mode_names[] = {
|
||||
{ HDMI_COLORSPACE_RGB, "rgb" },
|
||||
{ HDMI_COLORSPACE_YUV422, "yuv422" },
|
||||
{ HDMI_COLORSPACE_YUV444, "yuv444" },
|
||||
};
|
||||
|
||||
#define DEFAULT_COLORSPACE_MODE HDMI_COLORSPACE_RGB
|
||||
|
||||
/**
|
||||
|
@ -45,7 +45,7 @@
|
||||
|
||||
static void ttm_bo_global_kobj_release(struct kobject *kobj);
|
||||
|
||||
/**
|
||||
/*
|
||||
* ttm_global_mutex - protecting the global BO state
|
||||
*/
|
||||
DEFINE_MUTEX(ttm_global_mutex);
|
||||
@ -278,7 +278,7 @@ out_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Call bo::reserved.
|
||||
* Will release GPU memory type usage on destruction.
|
||||
* This is the place to put in driver specific hooks to release
|
||||
@ -352,9 +352,10 @@ static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo)
|
||||
* Must be called with lru_lock and reservation held, this function
|
||||
* will drop the lru lock and optionally the reservation lock before returning.
|
||||
*
|
||||
* @interruptible Any sleeps should occur interruptibly.
|
||||
* @no_wait_gpu Never wait for gpu. Return -EBUSY instead.
|
||||
* @unlock_resv Unlock the reservation lock as well.
|
||||
* @bo: The buffer object to clean-up
|
||||
* @interruptible: Any sleeps should occur interruptibly.
|
||||
* @no_wait_gpu: Never wait for gpu. Return -EBUSY instead.
|
||||
* @unlock_resv: Unlock the reservation lock as well.
|
||||
*/
|
||||
|
||||
static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,
|
||||
@ -420,7 +421,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Traverse the delayed list, and call ttm_bo_cleanup_refs on all
|
||||
* encountered buffers.
|
||||
*/
|
||||
@ -628,7 +629,7 @@ bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
|
||||
}
|
||||
EXPORT_SYMBOL(ttm_bo_eviction_valuable);
|
||||
|
||||
/**
|
||||
/*
|
||||
* Check the target bo is allowable to be evicted or swapout, including cases:
|
||||
*
|
||||
* a. if share same reservation object with ctx->resv, have assumption
|
||||
@ -767,7 +768,7 @@ int ttm_mem_evict_first(struct ttm_bo_device *bdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Add the last move fence to the BO and reserve a new shared slot.
|
||||
*/
|
||||
static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,
|
||||
@ -803,7 +804,7 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Repeatedly evict memory from the LRU for @mem_type until we create enough
|
||||
* space, or we've evicted everything and there isn't enough space.
|
||||
*/
|
||||
@ -865,7 +866,7 @@ static int ttm_bo_mem_placement(struct ttm_buffer_object *bo,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Creates space for memory region @mem according to its type.
|
||||
*
|
||||
* This function first searches for free space in compatible memory types in
|
||||
@ -1430,7 +1431,7 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,
|
||||
}
|
||||
EXPORT_SYMBOL(ttm_bo_wait);
|
||||
|
||||
/**
|
||||
/*
|
||||
* A buffer object shrink method that tries to swap out the first
|
||||
* buffer object on the bo_global::swap_lru list.
|
||||
*/
|
||||
|
@ -135,7 +135,7 @@ static void ttm_pool_free_page(struct ttm_pool *pool, enum ttm_caching caching,
|
||||
set_pages_wb(p, 1 << order);
|
||||
#endif
|
||||
|
||||
if (!pool->use_dma_alloc) {
|
||||
if (!pool || !pool->use_dma_alloc) {
|
||||
__free_pages(p, order);
|
||||
return;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
/**
|
||||
/*
|
||||
* Currently we use a spinlock for the lock, but a mutex *may* be
|
||||
* more appropriate to reduce scheduling latency if the range manager
|
||||
* ends up with very fragmented allocation patterns.
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include <drm/drm_cache.h>
|
||||
#include <drm/ttm/ttm_bo_driver.h>
|
||||
|
||||
/**
|
||||
/*
|
||||
* Allocates a ttm structure for the given BO.
|
||||
*/
|
||||
int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
|
||||
@ -73,7 +73,7 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Allocates storage for pointers to the pages that back the ttm.
|
||||
*/
|
||||
static int ttm_tt_alloc_page_directory(struct ttm_tt *ttm)
|
||||
|
@ -305,8 +305,10 @@ static int udl_handle_damage(struct drm_framebuffer *fb, int x, int y,
|
||||
vaddr = map.vaddr; /* TODO: Use mapping abstraction properly */
|
||||
|
||||
urb = udl_get_urb(dev);
|
||||
if (!urb)
|
||||
if (!urb) {
|
||||
ret = -ENOMEM;
|
||||
goto out_drm_gem_shmem_vunmap;
|
||||
}
|
||||
cmd = urb->transfer_buffer;
|
||||
|
||||
for (i = clip.y1; i < clip.y2; i++) {
|
||||
|
@ -38,42 +38,6 @@
|
||||
#define DRIVER_MINOR 0
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int v3d_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(dev);
|
||||
struct v3d_dev *v3d = to_v3d_dev(drm);
|
||||
|
||||
v3d_irq_disable(v3d);
|
||||
|
||||
clk_disable_unprepare(v3d->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int v3d_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(dev);
|
||||
struct v3d_dev *v3d = to_v3d_dev(drm);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(v3d->clk);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* XXX: VPM base */
|
||||
|
||||
v3d_mmu_set_page_table(v3d);
|
||||
v3d_irq_enable(v3d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops v3d_v3d_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(v3d_runtime_suspend, v3d_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static int v3d_get_param_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
|
@ -275,6 +275,8 @@ v3d_lock_bo_reservations(struct v3d_job *job,
|
||||
* @dev: DRM device
|
||||
* @file_priv: DRM file for this fd
|
||||
* @job: V3D job being set up
|
||||
* @bo_handles: GEM handles
|
||||
* @bo_count: Number of GEM handles passed in
|
||||
*
|
||||
* The command validator needs to reference BOs by their index within
|
||||
* the submitted job's BO list. This does the validation of the job's
|
||||
|
@ -63,7 +63,7 @@ v3d_job_free(struct drm_sched_job *sched_job)
|
||||
v3d_job_put(job);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Returns the fences that the job depends on, one by one.
|
||||
*
|
||||
* If placed in the scheduler's .dependency method, the corresponding
|
||||
|
@ -391,7 +391,7 @@ static const struct drm_gem_object_funcs vc4_gem_object_funcs = {
|
||||
};
|
||||
|
||||
/**
|
||||
* vc4_gem_create_object - Implementation of driver->gem_create_object.
|
||||
* vc4_create_object - Implementation of driver->gem_create_object.
|
||||
* @dev: DRM device
|
||||
* @size: Size in bytes of the memory the object will reference
|
||||
*
|
||||
|
@ -16,7 +16,7 @@ struct vc4_debugfs_info_entry {
|
||||
struct drm_info_list info;
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Called at drm_dev_register() time on each of the minors registered
|
||||
* by the DRM device, to attach the debugfs files.
|
||||
*/
|
||||
@ -46,7 +46,7 @@ static int vc4_debugfs_regset32(struct seq_file *m, void *unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Registers a debugfs file with a callback function for a vc4 component.
|
||||
*
|
||||
* This is like drm_debugfs_create_files(), but that can only be
|
||||
|
@ -331,9 +331,8 @@ static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
|
||||
{
|
||||
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
|
||||
union hdmi_infoframe frame;
|
||||
int ret;
|
||||
|
||||
ret = hdmi_audio_infoframe_init(&frame.audio);
|
||||
hdmi_audio_infoframe_init(&frame.audio);
|
||||
|
||||
frame.audio.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
|
||||
frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
|
||||
|
@ -142,7 +142,7 @@ struct vc4_hdmi_register {
|
||||
#define VC5_RAM_REG(reg, offset) _VC4_REG(VC5_RAM, reg, offset)
|
||||
#define VC5_RM_REG(reg, offset) _VC4_REG(VC5_RM, reg, offset)
|
||||
|
||||
static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
|
||||
static const struct vc4_hdmi_register __maybe_unused vc4_hdmi_fields[] = {
|
||||
VC4_HD_REG(HDMI_M_CTL, 0x000c),
|
||||
VC4_HD_REG(HDMI_MAI_CTL, 0x0014),
|
||||
VC4_HD_REG(HDMI_MAI_THR, 0x0018),
|
||||
@ -203,7 +203,7 @@ static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
|
||||
VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
|
||||
};
|
||||
|
||||
static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
|
||||
static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi0_fields[] = {
|
||||
VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
|
||||
VC4_HD_REG(HDMI_MAI_CTL, 0x0010),
|
||||
VC4_HD_REG(HDMI_MAI_THR, 0x0014),
|
||||
@ -279,7 +279,7 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
|
||||
VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
|
||||
};
|
||||
|
||||
static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
|
||||
static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi1_fields[] = {
|
||||
VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
|
||||
VC4_HD_REG(HDMI_MAI_CTL, 0x0030),
|
||||
VC4_HD_REG(HDMI_MAI_THR, 0x0034),
|
||||
|
@ -122,7 +122,7 @@ static int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Wraps pm_runtime_get_sync() in a refcount, so that we can reliably
|
||||
* get the pm_runtime refcount to 0 in vc4_reset().
|
||||
*/
|
||||
@ -205,7 +205,7 @@ try_again:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* bin_bo_alloc() - allocates the memory that will be used for
|
||||
* tile binning.
|
||||
*
|
||||
|
@ -593,13 +593,11 @@ static inline void via_dummy_bitblt(drm_via_private_t *dev_priv)
|
||||
|
||||
static void via_cmdbuf_jump(drm_via_private_t *dev_priv)
|
||||
{
|
||||
uint32_t agp_base;
|
||||
uint32_t pause_addr_lo, pause_addr_hi;
|
||||
uint32_t jump_addr_lo, jump_addr_hi;
|
||||
volatile uint32_t *last_pause_ptr;
|
||||
uint32_t dma_low_save1, dma_low_save2;
|
||||
|
||||
agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
|
||||
via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
|
||||
&jump_addr_lo, 0);
|
||||
|
||||
|
@ -43,7 +43,7 @@ static int virtgpu_virtio_get_uuid(struct dma_buf *buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct virtio_dma_buf_ops virtgpu_dmabuf_ops = {
|
||||
static const struct virtio_dma_buf_ops virtgpu_dmabuf_ops = {
|
||||
.ops = {
|
||||
.cache_sgt_mapping = true,
|
||||
.attach = virtio_dma_buf_attach,
|
||||
|
@ -1345,24 +1345,6 @@ static int sisusbdummycon_blank(struct vc_data *vc, int blank, int mode_switch)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sisusbdummycon_font_set(struct vc_data *vc,
|
||||
struct console_font *font,
|
||||
unsigned int flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sisusbdummycon_font_default(struct vc_data *vc,
|
||||
struct console_font *font, char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sisusbdummycon_font_copy(struct vc_data *vc, int con)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct consw sisusb_dummy_con = {
|
||||
.owner = THIS_MODULE,
|
||||
.con_startup = sisusbdummycon_startup,
|
||||
@ -1375,9 +1357,6 @@ static const struct consw sisusb_dummy_con = {
|
||||
.con_scroll = sisusbdummycon_scroll,
|
||||
.con_switch = sisusbdummycon_switch,
|
||||
.con_blank = sisusbdummycon_blank,
|
||||
.con_font_set = sisusbdummycon_font_set,
|
||||
.con_font_default = sisusbdummycon_font_default,
|
||||
.con_font_copy = sisusbdummycon_font_copy,
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -124,23 +124,6 @@ static int dummycon_switch(struct vc_data *vc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummycon_font_set(struct vc_data *vc, struct console_font *font,
|
||||
unsigned int flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummycon_font_default(struct vc_data *vc,
|
||||
struct console_font *font, char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummycon_font_copy(struct vc_data *vc, int con)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The console `switch' structure for the dummy console
|
||||
*
|
||||
@ -159,8 +142,5 @@ const struct consw dummy_con = {
|
||||
.con_scroll = dummycon_scroll,
|
||||
.con_switch = dummycon_switch,
|
||||
.con_blank = dummycon_blank,
|
||||
.con_font_set = dummycon_font_set,
|
||||
.con_font_default = dummycon_font_default,
|
||||
.con_font_copy = dummycon_font_copy,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(dummy_con);
|
||||
|
@ -506,7 +506,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
|
||||
fbfont->width, fbfont->height, fbfont->name);
|
||||
|
||||
bpc = ((fbfont->width+7)/8) * fbfont->height;
|
||||
size = bpc * 256;
|
||||
size = bpc * fbfont->charcount;
|
||||
size += sizeof(struct sti_rom_font);
|
||||
|
||||
nf = kzalloc(size, STI_LOWMEM);
|
||||
@ -514,7 +514,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
|
||||
return NULL;
|
||||
|
||||
nf->first_char = 0;
|
||||
nf->last_char = 255;
|
||||
nf->last_char = fbfont->charcount - 1;
|
||||
nf->width = fbfont->width;
|
||||
nf->height = fbfont->height;
|
||||
nf->font_type = STI_FONT_HPROMAN8;
|
||||
@ -525,7 +525,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
|
||||
|
||||
dest = nf;
|
||||
dest += sizeof(struct sti_rom_font);
|
||||
memcpy(dest, fbfont->data, bpc*256);
|
||||
memcpy(dest, fbfont->data, bpc * fbfont->charcount);
|
||||
|
||||
cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
|
||||
if (!cooked_font) {
|
||||
@ -660,7 +660,7 @@ static int sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
|
||||
void sti_font_convert_bytemode(struct sti_struct *sti, struct sti_cooked_font *f)
|
||||
{
|
||||
unsigned char *n, *p, *q;
|
||||
int size = f->raw->bytes_per_char * 256 + sizeof(struct sti_rom_font);
|
||||
int size = f->raw->bytes_per_char * (f->raw->last_char + 1) + sizeof(struct sti_rom_font);
|
||||
struct sti_rom_font *old_font;
|
||||
|
||||
if (sti->wordmode)
|
||||
|
@ -987,8 +987,8 @@ static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&pdata->pwr_gpios);
|
||||
ret = -ENOMEM;
|
||||
for (i = 0; i < gpiod_count(dev, "atmel,power-control"); i++) {
|
||||
ret = -ENOMEM;
|
||||
gpiod = devm_gpiod_get_index(dev, "atmel,power-control",
|
||||
i, GPIOD_ASIS);
|
||||
if (IS_ERR(gpiod))
|
||||
|
@ -404,6 +404,3 @@ void fbcon_set_bitops(struct fbcon_ops *ops)
|
||||
if (ops->rotate)
|
||||
fbcon_set_rotate(ops);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(fbcon_set_bitops);
|
||||
|
||||
|
@ -76,7 +76,7 @@ static const struct fb_cmap default_16_colors = {
|
||||
|
||||
|
||||
/**
|
||||
* fb_alloc_cmap - allocate a colormap
|
||||
* fb_alloc_cmap_gfp - allocate a colormap
|
||||
* @cmap: frame buffer colormap structure
|
||||
* @len: length of @cmap
|
||||
* @transp: boolean, 1 if there is transparency, 0 otherwise
|
||||
|
@ -1004,7 +1004,7 @@ static const char *fbcon_startup(void)
|
||||
vc->vc_font.width = font->width;
|
||||
vc->vc_font.height = font->height;
|
||||
vc->vc_font.data = (void *)(p->fontdata = font->data);
|
||||
vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */
|
||||
vc->vc_font.charcount = font->charcount;
|
||||
} else {
|
||||
p->fontdata = vc->vc_font.data;
|
||||
}
|
||||
@ -1032,8 +1032,8 @@ static void fbcon_init(struct vc_data *vc, int init)
|
||||
struct vc_data **default_mode = vc->vc_display_fg;
|
||||
struct vc_data *svc = *default_mode;
|
||||
struct fbcon_display *t, *p = &fb_display[vc->vc_num];
|
||||
int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256;
|
||||
int cap, ret;
|
||||
int logo = 1, new_rows, new_cols, rows, cols;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(info_idx == -1))
|
||||
return;
|
||||
@ -1042,7 +1042,6 @@ static void fbcon_init(struct vc_data *vc, int init)
|
||||
con2fb_map[vc->vc_num] = info_idx;
|
||||
|
||||
info = registered_fb[con2fb_map[vc->vc_num]];
|
||||
cap = info->flags;
|
||||
|
||||
if (logo_shown < 0 && console_loglevel <= CONSOLE_LOGLEVEL_QUIET)
|
||||
logo_shown = FBCON_LOGO_DONTSHOW;
|
||||
@ -1068,6 +1067,7 @@ static void fbcon_init(struct vc_data *vc, int init)
|
||||
fvc->vc_font.data);
|
||||
vc->vc_font.width = fvc->vc_font.width;
|
||||
vc->vc_font.height = fvc->vc_font.height;
|
||||
vc->vc_font.charcount = fvc->vc_font.charcount;
|
||||
p->userfont = t->userfont;
|
||||
|
||||
if (p->userfont)
|
||||
@ -1083,17 +1083,13 @@ static void fbcon_init(struct vc_data *vc, int init)
|
||||
vc->vc_font.width = font->width;
|
||||
vc->vc_font.height = font->height;
|
||||
vc->vc_font.data = (void *)(p->fontdata = font->data);
|
||||
vc->vc_font.charcount = 256; /* FIXME Need to
|
||||
support more fonts */
|
||||
vc->vc_font.charcount = font->charcount;
|
||||
}
|
||||
}
|
||||
|
||||
if (p->userfont)
|
||||
charcnt = FNTCHARCNT(p->fontdata);
|
||||
|
||||
vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
|
||||
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
|
||||
if (charcnt == 256) {
|
||||
if (vc->vc_font.charcount == 256) {
|
||||
vc->vc_hi_font_mask = 0;
|
||||
} else {
|
||||
vc->vc_hi_font_mask = 0x100;
|
||||
@ -1147,11 +1143,13 @@ static void fbcon_init(struct vc_data *vc, int init)
|
||||
|
||||
ops->graphics = 0;
|
||||
|
||||
if ((cap & FBINFO_HWACCEL_COPYAREA) &&
|
||||
!(cap & FBINFO_HWACCEL_DISABLED))
|
||||
p->scrollmode = SCROLL_MOVE;
|
||||
else /* default to something safe */
|
||||
p->scrollmode = SCROLL_REDRAW;
|
||||
/*
|
||||
* 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
|
||||
@ -1358,7 +1356,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
|
||||
struct vc_data **default_mode, *vc;
|
||||
struct vc_data *svc;
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
int rows, cols, charcnt = 256;
|
||||
int rows, cols;
|
||||
|
||||
p = &fb_display[unit];
|
||||
|
||||
@ -1378,12 +1376,11 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
|
||||
vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
|
||||
vc->vc_font.width = (*default_mode)->vc_font.width;
|
||||
vc->vc_font.height = (*default_mode)->vc_font.height;
|
||||
vc->vc_font.charcount = (*default_mode)->vc_font.charcount;
|
||||
p->userfont = t->userfont;
|
||||
if (p->userfont)
|
||||
REFCOUNT(p->fontdata)++;
|
||||
}
|
||||
if (p->userfont)
|
||||
charcnt = FNTCHARCNT(p->fontdata);
|
||||
|
||||
var->activate = FB_ACTIVATE_NOW;
|
||||
info->var.activate = var->activate;
|
||||
@ -1393,7 +1390,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
|
||||
ops->var = info->var;
|
||||
vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
|
||||
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
|
||||
if (charcnt == 256) {
|
||||
if (vc->vc_font.charcount == 256) {
|
||||
vc->vc_hi_font_mask = 0;
|
||||
} else {
|
||||
vc->vc_hi_font_mask = 0x100;
|
||||
@ -1961,45 +1958,15 @@ static void updatescrollmode(struct fbcon_display *p,
|
||||
{
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
int fh = vc->vc_font.height;
|
||||
int cap = info->flags;
|
||||
u16 t = 0;
|
||||
int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep,
|
||||
info->fix.xpanstep);
|
||||
int ywrap = FBCON_SWAP(ops->rotate, info->fix.ywrapstep, t);
|
||||
int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
|
||||
int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual,
|
||||
info->var.xres_virtual);
|
||||
int good_pan = (cap & FBINFO_HWACCEL_YPAN) &&
|
||||
divides(ypan, vc->vc_font.height) && vyres > yres;
|
||||
int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) &&
|
||||
divides(ywrap, vc->vc_font.height) &&
|
||||
divides(vc->vc_font.height, vyres) &&
|
||||
divides(vc->vc_font.height, yres);
|
||||
int reading_fast = cap & FBINFO_READS_FAST;
|
||||
int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) &&
|
||||
!(cap & FBINFO_HWACCEL_DISABLED);
|
||||
int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) &&
|
||||
!(cap & FBINFO_HWACCEL_DISABLED);
|
||||
|
||||
p->vrows = vyres/fh;
|
||||
if (yres > (fh * (vc->vc_rows + 1)))
|
||||
p->vrows -= (yres - (fh * vc->vc_rows)) / fh;
|
||||
if ((yres % fh) && (vyres % fh < yres % fh))
|
||||
p->vrows--;
|
||||
|
||||
if (good_wrap || good_pan) {
|
||||
if (reading_fast || fast_copyarea)
|
||||
p->scrollmode = good_wrap ?
|
||||
SCROLL_WRAP_MOVE : SCROLL_PAN_MOVE;
|
||||
else
|
||||
p->scrollmode = good_wrap ? SCROLL_REDRAW :
|
||||
SCROLL_PAN_REDRAW;
|
||||
} else {
|
||||
if (reading_fast || (fast_copyarea && !fast_imageblit))
|
||||
p->scrollmode = SCROLL_MOVE;
|
||||
else
|
||||
p->scrollmode = SCROLL_REDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
#define PITCH(w) (((w) + 7) >> 3)
|
||||
@ -2027,7 +1994,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
|
||||
*/
|
||||
if (pitch <= 0)
|
||||
return -EINVAL;
|
||||
size = CALC_FONTSZ(vc->vc_font.height, pitch, FNTCHARCNT(vc->vc_font.data));
|
||||
size = CALC_FONTSZ(vc->vc_font.height, pitch, vc->vc_font.charcount);
|
||||
if (size > FNTSIZE(vc->vc_font.data))
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -2075,7 +2042,7 @@ static int fbcon_switch(struct vc_data *vc)
|
||||
struct fbcon_ops *ops;
|
||||
struct fbcon_display *p = &fb_display[vc->vc_num];
|
||||
struct fb_var_screeninfo var;
|
||||
int i, ret, prev_console, charcnt = 256;
|
||||
int i, ret, prev_console;
|
||||
|
||||
info = registered_fb[con2fb_map[vc->vc_num]];
|
||||
ops = info->fbcon_par;
|
||||
@ -2152,10 +2119,7 @@ static int fbcon_switch(struct vc_data *vc)
|
||||
vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
|
||||
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
|
||||
|
||||
if (p->userfont)
|
||||
charcnt = FNTCHARCNT(vc->vc_font.data);
|
||||
|
||||
if (charcnt > 256)
|
||||
if (vc->vc_font.charcount > 256)
|
||||
vc->vc_complement_mask <<= 1;
|
||||
|
||||
updatescrollmode(p, info, vc);
|
||||
@ -2405,31 +2369,27 @@ static void set_vc_hi_font(struct vc_data *vc, bool set)
|
||||
}
|
||||
}
|
||||
|
||||
static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
|
||||
static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
|
||||
const u8 * data, int userfont)
|
||||
{
|
||||
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];
|
||||
int resize;
|
||||
int cnt;
|
||||
char *old_data = NULL;
|
||||
|
||||
resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
|
||||
if (p->userfont)
|
||||
old_data = vc->vc_font.data;
|
||||
if (userfont)
|
||||
cnt = FNTCHARCNT(data);
|
||||
else
|
||||
cnt = 256;
|
||||
vc->vc_font.data = (void *)(p->fontdata = data);
|
||||
if ((p->userfont = userfont))
|
||||
REFCOUNT(data)++;
|
||||
vc->vc_font.width = w;
|
||||
vc->vc_font.height = h;
|
||||
if (vc->vc_hi_font_mask && cnt == 256)
|
||||
vc->vc_font.charcount = charcount;
|
||||
if (vc->vc_hi_font_mask && charcount == 256)
|
||||
set_vc_hi_font(vc, false);
|
||||
else if (!vc->vc_hi_font_mask && cnt == 512)
|
||||
else if (!vc->vc_hi_font_mask && charcount == 512)
|
||||
set_vc_hi_font(vc, true);
|
||||
|
||||
if (resize) {
|
||||
@ -2451,16 +2411,6 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fbcon_copy_font(struct vc_data *vc, int con)
|
||||
{
|
||||
struct fbcon_display *od = &fb_display[con];
|
||||
struct console_font *f = &vc->vc_font;
|
||||
|
||||
if (od->fontdata == f->data)
|
||||
return 0; /* already the same font... */
|
||||
return fbcon_do_set_font(vc, f->width, f->height, od->fontdata, od->userfont);
|
||||
}
|
||||
|
||||
/*
|
||||
* User asked to set font; we are guaranteed that
|
||||
* a) width and height are in range 1..32
|
||||
@ -2506,9 +2456,10 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
|
||||
if (!new_data)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(new_data, 0, FONT_EXTRA_WORDS * sizeof(int));
|
||||
|
||||
new_data += FONT_EXTRA_WORDS * sizeof(int);
|
||||
FNTSIZE(new_data) = size;
|
||||
FNTCHARCNT(new_data) = charcount;
|
||||
REFCOUNT(new_data) = 0; /* usage counter */
|
||||
for (i=0; i< charcount; i++) {
|
||||
memcpy(new_data + i*h*pitch, data + i*32*pitch, h*pitch);
|
||||
@ -2534,7 +2485,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
|
||||
break;
|
||||
}
|
||||
}
|
||||
return fbcon_do_set_font(vc, font->width, font->height, new_data, 1);
|
||||
return fbcon_do_set_font(vc, font->width, font->height, charcount, new_data, 1);
|
||||
}
|
||||
|
||||
static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name)
|
||||
@ -2550,7 +2501,7 @@ static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, cha
|
||||
|
||||
font->width = f->width;
|
||||
font->height = f->height;
|
||||
return fbcon_do_set_font(vc, f->width, f->height, f->data, 0);
|
||||
return fbcon_do_set_font(vc, f->width, f->height, f->charcount, f->data, 0);
|
||||
}
|
||||
|
||||
static u16 palette_red[16];
|
||||
@ -3019,7 +2970,6 @@ void fbcon_get_requirement(struct fb_info *info,
|
||||
struct fb_blit_caps *caps)
|
||||
{
|
||||
struct vc_data *vc;
|
||||
struct fbcon_display *p;
|
||||
|
||||
if (caps->flags) {
|
||||
int i, charcnt;
|
||||
@ -3028,11 +2978,9 @@ void fbcon_get_requirement(struct fb_info *info,
|
||||
vc = vc_cons[i].d;
|
||||
if (vc && vc->vc_mode == KD_TEXT &&
|
||||
info->node == con2fb_map[i]) {
|
||||
p = &fb_display[i];
|
||||
caps->x |= 1 << (vc->vc_font.width - 1);
|
||||
caps->y |= 1 << (vc->vc_font.height - 1);
|
||||
charcnt = (p->userfont) ?
|
||||
FNTCHARCNT(p->fontdata) : 256;
|
||||
charcnt = vc->vc_font.charcount;
|
||||
if (caps->len < charcnt)
|
||||
caps->len = charcnt;
|
||||
}
|
||||
@ -3042,11 +2990,9 @@ void fbcon_get_requirement(struct fb_info *info,
|
||||
|
||||
if (vc && vc->vc_mode == KD_TEXT &&
|
||||
info->node == con2fb_map[fg_console]) {
|
||||
p = &fb_display[fg_console];
|
||||
caps->x = 1 << (vc->vc_font.width - 1);
|
||||
caps->y = 1 << (vc->vc_font.height - 1);
|
||||
caps->len = (p->userfont) ?
|
||||
FNTCHARCNT(p->fontdata) : 256;
|
||||
caps->len = vc->vc_font.charcount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3111,7 +3057,6 @@ static const struct consw fb_con = {
|
||||
.con_font_set = fbcon_set_font,
|
||||
.con_font_get = fbcon_get_font,
|
||||
.con_font_default = fbcon_set_def_font,
|
||||
.con_font_copy = fbcon_copy_font,
|
||||
.con_set_palette = fbcon_set_palette,
|
||||
.con_invert_region = fbcon_invert_region,
|
||||
.con_screen_pos = fbcon_screen_pos,
|
||||
|
@ -409,4 +409,3 @@ void fbcon_rotate_ccw(struct fbcon_ops *ops)
|
||||
ops->cursor = ccw_cursor;
|
||||
ops->update_start = ccw_update_start;
|
||||
}
|
||||
EXPORT_SYMBOL(fbcon_rotate_ccw);
|
||||
|
@ -392,4 +392,3 @@ void fbcon_rotate_cw(struct fbcon_ops *ops)
|
||||
ops->cursor = cw_cursor;
|
||||
ops->update_start = cw_update_start;
|
||||
}
|
||||
EXPORT_SYMBOL(fbcon_rotate_cw);
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <linux/fb.h>
|
||||
#include <linux/vt_kern.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/font.h>
|
||||
#include <asm/types.h>
|
||||
#include "fbcon.h"
|
||||
#include "fbcon_rotate.h"
|
||||
@ -33,7 +32,7 @@ static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc)
|
||||
|
||||
src = ops->fontdata = vc->vc_font.data;
|
||||
ops->cur_rotate = ops->p->con_rotate;
|
||||
len = (!ops->p->userfont) ? 256 : FNTCHARCNT(src);
|
||||
len = vc->vc_font.charcount;
|
||||
s_cellsize = ((vc->vc_font.width + 7)/8) *
|
||||
vc->vc_font.height;
|
||||
d_cellsize = s_cellsize;
|
||||
@ -110,4 +109,3 @@ void fbcon_set_rotate(struct fbcon_ops *ops)
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(fbcon_set_rotate);
|
||||
|
@ -436,4 +436,3 @@ void fbcon_rotate_ud(struct fbcon_ops *ops)
|
||||
ops->cursor = ud_cursor;
|
||||
ops->update_start = ud_update_start;
|
||||
}
|
||||
EXPORT_SYMBOL(fbcon_rotate_ud);
|
||||
|
@ -74,5 +74,3 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
|
||||
info->fbops->fb_imageblit(info, image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(soft_cursor);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user