Merge tag 'drm-misc-next-2017-11-30' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

Cross-subsystem Changes:

- device tree doc for the Mitsubishi AA070MC01 and Tianma TM070RVHG71
panels (Lukasz Majewski) and for a 2nd endpoint on stm32 (Philippe Cornu)

Core Changes:

The most important changes are:

- Add drm_driver .last_close and .output_poll_changed helpers to reduce
fbdev emulation footprint in drivers (Noralf)
- Fix plane clipping in core and for vmwgfx (Ville)

Then we have a bunch of of improvement for print and debug such as the
addition of a framebuffer debugfs file. ELD connector, HDMI and
improvements.  And a bunch of misc improvements, clean ups and style
changes and doc updates

[airlied: drop eld bits from amdgpu_dm]

Driver Changes:

- sii8620: filter unsupported modes and add DVI mode support (Maciej Purski)
- rockchip: analogix_dp: Remove unnecessary init code (Jeffy Chen)
- virtio, cirrus: add fb create_handle support to enable screenshots(Lepton Wu)
- virtio: replace reference/unreference with get/put (Aastha Gupta)
- vc4, gma500: Convert timers to use timer_setup() (Kees Cook)
- vc4: Reject HDMI modes with too high of clocks (Eric)
- vc4: Add support for more pixel formats (Dave Stevenson)
- stm: dsi: Rename driver name to "stm32-display-dsi" (Philippe Cornu)
- stm: ltdc: add a 2nd endpoint (Philippe Cornu)
- via: use monotonic time for VIA_WAIT_IRQ (Arnd Bergmann)

* tag 'drm-misc-next-2017-11-30' of git://anongit.freedesktop.org/drm/drm-misc: (96 commits)
  drm/bridge: tc358767: add copyright lines
  MAINTAINERS: change maintainer for Rockchip drm drivers
  drm/vblank: Fix vblank timestamp debugs
  drm/via: use monotonic time for VIA_WAIT_IRQ
  dma-buf: Fix ifnullfree.cocci warnings
  drm/printer: Add drm_vprintf()
  drm/edid: Allow HDMI infoframe without VIC or S3D
  video/hdmi: Allow "empty" HDMI infoframes
  dma-buf/fence: Fix lock inversion within dma-fence-array
  drm/sti: Handle return value of platform_get_irq_byname
  drm/vc4: Add support for NV21 and NV61.
  drm/vc4: Use .pixel_order instead of custom .flip_cbcr
  drm/vc4: Add support for DRM_FORMAT_RGB888 and DRM_FORMAT_BGR888
  drm: Move drm_plane_helper_check_state() into drm_atomic_helper.c
  drm: Check crtc_state->enable rather than crtc->enabled in drm_plane_helper_check_state()
  drm/vmwgfx: Try to fix plane clipping
  drm/vmwgfx: Use drm_plane_helper_check_state()
  drm/vmwgfx: Remove bogus crtc coords vs fb size check
  gpu: gma500: remove unneeded DRIVER_LICENSE #define
  drm: don't link DP aux i2c adapter to the hardware device node
  ...
This commit is contained in:
Dave Airlie 2017-12-04 05:38:52 +10:00
commit 2c1c55cb75
113 changed files with 1325 additions and 873 deletions

View File

@ -0,0 +1,7 @@
Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel
Required properties:
- compatible: should be "mitsubishi,aa070mc01-ca1"
This binding is compatible with the simple-panel binding, which is specified
in simple-panel.txt in this directory.

View File

@ -0,0 +1,29 @@
Tianma Micro-electronics TM070RVHG71 7.0" WXGA TFT LCD panel
Required properties:
- compatible: should be "tianma,tm070rvhg71"
- power-supply: single regulator to provide the supply voltage
- backlight: phandle of the backlight device attached to the panel
Required nodes:
- port: LVDS port mapping to connect this display
This panel needs single power supply voltage. Its backlight is conntrolled
via PWM signal.
Example:
--------
Example device-tree definition when connected to iMX6Q based board
panel: panel-lvds0 {
compatible = "tianma,tm070rvhg71";
backlight = <&backlight_lvds>;
power-supply = <&reg_lvds>;
port {
panel_in_lvds0: endpoint {
remote-endpoint = <&lvds0_out>;
};
};
};

View File

@ -7,6 +7,7 @@ buffer to an external LCD interface.
Required properties: Required properties:
- compatible: value should be one of the following - compatible: value should be one of the following
"rockchip,rk3036-vop"; "rockchip,rk3036-vop";
"rockchip,rk3126-vop";
"rockchip,rk3288-vop"; "rockchip,rk3288-vop";
"rockchip,rk3368-vop"; "rockchip,rk3368-vop";
"rockchip,rk3366-vop"; "rockchip,rk3366-vop";

View File

@ -10,7 +10,11 @@
- "lcd" for the clock feeding the output pixel clock & IP clock. - "lcd" for the clock feeding the output pixel clock & IP clock.
- resets: reset to be used by the device (defined by use of RCC macro). - resets: reset to be used by the device (defined by use of RCC macro).
Required nodes: Required nodes:
- Video port for RGB output. - Video port for DPI RGB output: ltdc has one video port with up to 2
endpoints:
- for external dpi rgb panel or bridge, using gpios.
- for internal dpi input of the MIPI DSI host controller.
Note: These 2 endpoints cannot be activated simultaneously.
* STMicroelectronics STM32 DSI controller specific extensions to Synopsys * STMicroelectronics STM32 DSI controller specific extensions to Synopsys
DesignWare MIPI DSI host controller DesignWare MIPI DSI host controller

View File

@ -179,6 +179,10 @@ don't do this, drivers used dev_info/warn/err to make this differentiation. We
now have DRM_DEV_* variants of the drm print macros, so we can start to convert now have DRM_DEV_* variants of the drm print macros, so we can start to convert
those drivers back to using drm-formwatted specific log messages. those drivers back to using drm-formwatted specific log messages.
Before you start this conversion please contact the relevant maintainers to make
sure your work will be merged - not everyone agrees that the DRM dmesg macros
are better.
Contact: Sean Paul, Maintainer of the driver you plan to convert Contact: Sean Paul, Maintainer of the driver you plan to convert
Core refactorings Core refactorings

View File

@ -4587,6 +4587,7 @@ F: include/linux/vga*
DRM DRIVERS AND MISC GPU PATCHES DRM DRIVERS AND MISC GPU PATCHES
M: Daniel Vetter <daniel.vetter@intel.com> M: Daniel Vetter <daniel.vetter@intel.com>
M: Jani Nikula <jani.nikula@linux.intel.com> M: Jani Nikula <jani.nikula@linux.intel.com>
M: Gustavo Padovan <gustavo@padovan.org>
M: Sean Paul <seanpaul@chromium.org> M: Sean Paul <seanpaul@chromium.org>
W: https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html W: https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html
S: Maintained S: Maintained
@ -4715,7 +4716,8 @@ F: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt
F: Documentation/devicetree/bindings/display/renesas,du.txt F: Documentation/devicetree/bindings/display/renesas,du.txt
DRM DRIVERS FOR ROCKCHIP DRM DRIVERS FOR ROCKCHIP
M: Mark Yao <mark.yao@rock-chips.com> M: Sandy Huang <hjc@rock-chips.com>
M: Heiko Stübner <heiko@sntech.de>
L: dri-devel@lists.freedesktop.org L: dri-devel@lists.freedesktop.org
S: Maintained S: Maintained
F: drivers/gpu/drm/rockchip/ F: drivers/gpu/drm/rockchip/

View File

@ -245,6 +245,7 @@ config DMA_SHARED_BUFFER
bool bool
default n default n
select ANON_INODES select ANON_INODES
select IRQ_WORK
help help
This option enables the framework for buffer-sharing between This option enables the framework for buffer-sharing between
multiple drivers. A buffer is associated with a file using driver multiple drivers. A buffer is associated with a file using driver

View File

@ -351,13 +351,13 @@ static inline int is_dma_buf_file(struct file *file)
* *
* 2. Userspace passes this file-descriptors to all drivers it wants this buffer * 2. Userspace passes this file-descriptors to all drivers it wants this buffer
* to share with: First the filedescriptor is converted to a &dma_buf using * to share with: First the filedescriptor is converted to a &dma_buf using
* dma_buf_get(). The the buffer is attached to the device using * dma_buf_get(). Then the buffer is attached to the device using
* dma_buf_attach(). * dma_buf_attach().
* *
* Up to this stage the exporter is still free to migrate or reallocate the * Up to this stage the exporter is still free to migrate or reallocate the
* backing storage. * backing storage.
* *
* 3. Once the buffer is attached to all devices userspace can inniate DMA * 3. Once the buffer is attached to all devices userspace can initiate DMA
* access to the shared buffer. In the kernel this is done by calling * access to the shared buffer. In the kernel this is done by calling
* dma_buf_map_attachment() and dma_buf_unmap_attachment(). * dma_buf_map_attachment() and dma_buf_unmap_attachment().
* *
@ -617,7 +617,7 @@ EXPORT_SYMBOL_GPL(dma_buf_detach);
* Returns sg_table containing the scatterlist to be returned; returns ERR_PTR * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
* on error. May return -EINTR if it is interrupted by a signal. * on error. May return -EINTR if it is interrupted by a signal.
* *
* A mapping must be unmapped again using dma_buf_map_attachment(). Note that * A mapping must be unmapped by using dma_buf_unmap_attachment(). Note that
* the underlying backing storage is pinned for as long as a mapping exists, * the underlying backing storage is pinned for as long as a mapping exists,
* therefore users/importers should not hold onto a mapping for undue amounts of * therefore users/importers should not hold onto a mapping for undue amounts of
* time. * time.
@ -1179,7 +1179,6 @@ static int dma_buf_init_debugfs(void)
static void dma_buf_uninit_debugfs(void) static void dma_buf_uninit_debugfs(void)
{ {
if (dma_buf_debugfs_dir)
debugfs_remove_recursive(dma_buf_debugfs_dir); debugfs_remove_recursive(dma_buf_debugfs_dir);
} }
#else #else

View File

@ -31,6 +31,14 @@ static const char *dma_fence_array_get_timeline_name(struct dma_fence *fence)
return "unbound"; return "unbound";
} }
static void irq_dma_fence_array_work(struct irq_work *wrk)
{
struct dma_fence_array *array = container_of(wrk, typeof(*array), work);
dma_fence_signal(&array->base);
dma_fence_put(&array->base);
}
static void dma_fence_array_cb_func(struct dma_fence *f, static void dma_fence_array_cb_func(struct dma_fence *f,
struct dma_fence_cb *cb) struct dma_fence_cb *cb)
{ {
@ -39,7 +47,8 @@ static void dma_fence_array_cb_func(struct dma_fence *f,
struct dma_fence_array *array = array_cb->array; struct dma_fence_array *array = array_cb->array;
if (atomic_dec_and_test(&array->num_pending)) if (atomic_dec_and_test(&array->num_pending))
dma_fence_signal(&array->base); irq_work_queue(&array->work);
else
dma_fence_put(&array->base); dma_fence_put(&array->base);
} }
@ -136,6 +145,7 @@ struct dma_fence_array *dma_fence_array_create(int num_fences,
spin_lock_init(&array->lock); spin_lock_init(&array->lock);
dma_fence_init(&array->base, &dma_fence_array_ops, &array->lock, dma_fence_init(&array->base, &dma_fence_array_ops, &array->lock,
context, seqno); context, seqno);
init_irq_work(&array->work, irq_dma_fence_array_work);
array->num_fences = num_fences; array->num_fences = num_fences;
atomic_set(&array->num_pending, signal_on_any ? 1 : num_fences); atomic_set(&array->num_pending, signal_on_any ? 1 : num_fences);

View File

@ -104,7 +104,8 @@ reservation_object_add_shared_inplace(struct reservation_object *obj,
struct reservation_object_list *fobj, struct reservation_object_list *fobj,
struct dma_fence *fence) struct dma_fence *fence)
{ {
u32 i; struct dma_fence *signaled = NULL;
u32 i, signaled_idx;
dma_fence_get(fence); dma_fence_get(fence);
@ -126,17 +127,28 @@ reservation_object_add_shared_inplace(struct reservation_object *obj,
dma_fence_put(old_fence); dma_fence_put(old_fence);
return; return;
} }
if (!signaled && dma_fence_is_signaled(old_fence)) {
signaled = old_fence;
signaled_idx = i;
}
} }
/* /*
* memory barrier is added by write_seqcount_begin, * memory barrier is added by write_seqcount_begin,
* fobj->shared_count is protected by this lock too * fobj->shared_count is protected by this lock too
*/ */
if (signaled) {
RCU_INIT_POINTER(fobj->shared[signaled_idx], fence);
} else {
RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence); RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence);
fobj->shared_count++; fobj->shared_count++;
}
write_seqcount_end(&obj->seq); write_seqcount_end(&obj->seq);
preempt_enable(); preempt_enable();
dma_fence_put(signaled);
} }
static void static void
@ -145,8 +157,7 @@ reservation_object_add_shared_replace(struct reservation_object *obj,
struct reservation_object_list *fobj, struct reservation_object_list *fobj,
struct dma_fence *fence) struct dma_fence *fence)
{ {
unsigned i; unsigned i, j, k;
struct dma_fence *old_fence = NULL;
dma_fence_get(fence); dma_fence_get(fence);
@ -162,24 +173,21 @@ reservation_object_add_shared_replace(struct reservation_object *obj,
* references from the old struct are carried over to * references from the old struct are carried over to
* the new. * the new.
*/ */
fobj->shared_count = old->shared_count; for (i = 0, j = 0, k = fobj->shared_max; i < old->shared_count; ++i) {
for (i = 0; i < old->shared_count; ++i) {
struct dma_fence *check; struct dma_fence *check;
check = rcu_dereference_protected(old->shared[i], check = rcu_dereference_protected(old->shared[i],
reservation_object_held(obj)); reservation_object_held(obj));
if (!old_fence && check->context == fence->context) { if (check->context == fence->context ||
old_fence = check; dma_fence_is_signaled(check))
RCU_INIT_POINTER(fobj->shared[i], fence); RCU_INIT_POINTER(fobj->shared[--k], check);
} else else
RCU_INIT_POINTER(fobj->shared[i], check); RCU_INIT_POINTER(fobj->shared[j++], check);
} }
if (!old_fence) { fobj->shared_count = j;
RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence); RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence);
fobj->shared_count++; fobj->shared_count++;
}
done: done:
preempt_disable(); preempt_disable();
@ -192,10 +200,18 @@ done:
write_seqcount_end(&obj->seq); write_seqcount_end(&obj->seq);
preempt_enable(); preempt_enable();
if (old) if (!old)
kfree_rcu(old, rcu); return;
dma_fence_put(old_fence); /* Drop the references to the signaled fences */
for (i = k; i < fobj->shared_max; ++i) {
struct dma_fence *f;
f = rcu_dereference_protected(fobj->shared[i],
reservation_object_held(obj));
dma_fence_put(f);
}
kfree_rcu(old, rcu);
} }
/** /**
@ -318,7 +334,7 @@ retry:
continue; continue;
} }
dst_list->shared[dst_list->shared_count++] = fence; rcu_assign_pointer(dst_list->shared[dst_list->shared_count++], fence);
} }
} else { } else {
dst_list = NULL; dst_list = NULL;

View File

@ -358,7 +358,6 @@ static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
if (amdgpu_connector->edid) { if (amdgpu_connector->edid) {
drm_mode_connector_update_edid_property(connector, amdgpu_connector->edid); drm_mode_connector_update_edid_property(connector, amdgpu_connector->edid);
ret = drm_add_edid_modes(connector, amdgpu_connector->edid); ret = drm_add_edid_modes(connector, amdgpu_connector->edid);
drm_edid_to_eld(connector, amdgpu_connector->edid);
return ret; return ret;
} }
drm_mode_connector_update_edid_property(connector, NULL); drm_mode_connector_update_edid_property(connector, NULL);

View File

@ -3333,8 +3333,6 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
amdgpu_dm_connector->num_modes = amdgpu_dm_connector->num_modes =
drm_add_edid_modes(connector, edid); drm_add_edid_modes(connector, edid);
drm_edid_to_eld(connector, edid);
amdgpu_dm_get_native_mode(connector); amdgpu_dm_get_native_mode(connector);
} else { } else {
amdgpu_dm_connector->num_modes = 0; amdgpu_dm_connector->num_modes = 0;

View File

@ -177,12 +177,7 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
static int dm_connector_update_modes(struct drm_connector *connector, static int dm_connector_update_modes(struct drm_connector *connector,
struct edid *edid) struct edid *edid)
{ {
int ret; return drm_add_edid_modes(connector, edid);
ret = drm_add_edid_modes(connector, edid);
drm_edid_to_eld(connector, edid);
return ret;
} }
static int dm_dp_mst_get_modes(struct drm_connector *connector) static int dm_dp_mst_get_modes(struct drm_connector *connector)

View File

@ -155,7 +155,6 @@ static int arcpgu_show_pxlclock(struct seq_file *m, void *arg)
static struct drm_info_list arcpgu_debugfs_list[] = { static struct drm_info_list arcpgu_debugfs_list[] = {
{ "clocks", arcpgu_show_pxlclock, 0 }, { "clocks", arcpgu_show_pxlclock, 0 },
{ "fb", drm_fb_cma_debugfs_show, 0 },
}; };
static int arcpgu_debugfs_init(struct drm_minor *minor) static int arcpgu_debugfs_init(struct drm_minor *minor)
@ -180,6 +179,7 @@ static struct drm_driver arcpgu_drm_driver = {
.prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle, .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_free_object_unlocked = drm_gem_cma_free_object, .gem_free_object_unlocked = drm_gem_cma_free_object,
.gem_print_info = drm_gem_cma_print_info,
.gem_vm_ops = &drm_gem_cma_vm_ops, .gem_vm_ops = &drm_gem_cma_vm_ops,
.gem_prime_export = drm_gem_prime_export, .gem_prime_export = drm_gem_prime_export,
.gem_prime_import = drm_gem_prime_import, .gem_prime_import = drm_gem_prime_import,

View File

@ -252,7 +252,7 @@ static int hdlcd_plane_atomic_check(struct drm_plane *plane,
clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.x2 = crtc_state->adjusted_mode.hdisplay;
clip.y2 = crtc_state->adjusted_mode.vdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay;
return drm_plane_helper_check_state(state, &clip, return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
false, true); false, true);

View File

@ -231,7 +231,6 @@ static int hdlcd_show_pxlclock(struct seq_file *m, void *arg)
static struct drm_info_list hdlcd_debugfs_list[] = { static struct drm_info_list hdlcd_debugfs_list[] = {
{ "interrupt_count", hdlcd_show_underrun_count, 0 }, { "interrupt_count", hdlcd_show_underrun_count, 0 },
{ "clocks", hdlcd_show_pxlclock, 0 }, { "clocks", hdlcd_show_pxlclock, 0 },
{ "fb", drm_fb_cma_debugfs_show, 0 },
}; };
static int hdlcd_debugfs_init(struct drm_minor *minor) static int hdlcd_debugfs_init(struct drm_minor *minor)
@ -253,6 +252,7 @@ static struct drm_driver hdlcd_driver = {
.irq_postinstall = hdlcd_irq_postinstall, .irq_postinstall = hdlcd_irq_postinstall,
.irq_uninstall = hdlcd_irq_uninstall, .irq_uninstall = hdlcd_irq_uninstall,
.gem_free_object_unlocked = drm_gem_cma_free_object, .gem_free_object_unlocked = drm_gem_cma_free_object,
.gem_print_info = drm_gem_cma_print_info,
.gem_vm_ops = &drm_gem_cma_vm_ops, .gem_vm_ops = &drm_gem_cma_vm_ops,
.dumb_create = drm_gem_cma_dumb_create, .dumb_create = drm_gem_cma_dumb_create,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_handle_to_fd = drm_gem_prime_handle_to_fd,

View File

@ -150,7 +150,8 @@ static int malidp_se_check_scaling(struct malidp_plane *mp,
clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.x2 = crtc_state->adjusted_mode.hdisplay;
clip.y2 = crtc_state->adjusted_mode.vdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay;
ret = drm_plane_helper_check_state(state, &clip, 0, INT_MAX, true, true); ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
0, INT_MAX, true, true);
if (ret) if (ret)
return ret; return ret;

View File

@ -977,8 +977,6 @@ static int anx78xx_get_modes(struct drm_connector *connector)
} }
num_modes = drm_add_edid_modes(connector, anx78xx->edid); num_modes = drm_add_edid_modes(connector, anx78xx->edid);
/* Store the ELD */
drm_edid_to_eld(connector, anx78xx->edid);
unlock: unlock:
mutex_unlock(&anx78xx->lock); mutex_unlock(&anx78xx->lock);

View File

@ -1169,8 +1169,18 @@ static void sii8620_set_infoframes(struct sii8620 *ctx)
sii8620_write_buf(ctx, REG_TPI_INFO_B0, buf, ret); sii8620_write_buf(ctx, REG_TPI_INFO_B0, buf, ret);
} }
static void sii8620_start_hdmi(struct sii8620 *ctx) static void sii8620_start_video(struct sii8620 *ctx)
{ {
if (!sii8620_is_mhl3(ctx))
sii8620_stop_video(ctx);
if (ctx->sink_type == SINK_DVI && !sii8620_is_mhl3(ctx)) {
sii8620_write(ctx, REG_RX_HDMI_CTRL2,
VAL_RX_HDMI_CTRL2_DEFVAL);
sii8620_write(ctx, REG_TPI_SC, 0);
return;
}
sii8620_write_seq_static(ctx, sii8620_write_seq_static(ctx,
REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL
| BIT_RX_HDMI_CTRL2_USE_AV_MUTE, | BIT_RX_HDMI_CTRL2_USE_AV_MUTE,
@ -1229,21 +1239,6 @@ static void sii8620_start_hdmi(struct sii8620 *ctx)
sii8620_set_infoframes(ctx); sii8620_set_infoframes(ctx);
} }
static void sii8620_start_video(struct sii8620 *ctx)
{
if (!sii8620_is_mhl3(ctx))
sii8620_stop_video(ctx);
switch (ctx->sink_type) {
case SINK_HDMI:
sii8620_start_hdmi(ctx);
break;
case SINK_DVI:
default:
break;
}
}
static void sii8620_disable_hpd(struct sii8620 *ctx) static void sii8620_disable_hpd(struct sii8620 *ctx)
{ {
sii8620_setbits(ctx, REG_EDID_CTRL, BIT_EDID_CTRL_EDID_PRIME_VALID, 0); sii8620_setbits(ctx, REG_EDID_CTRL, BIT_EDID_CTRL_EDID_PRIME_VALID, 0);
@ -1945,8 +1940,13 @@ static void sii8620_irq_scdt(struct sii8620 *ctx)
if (stat & BIT_INTR_SCDT_CHANGE) { if (stat & BIT_INTR_SCDT_CHANGE) {
u8 cstat = sii8620_readb(ctx, REG_TMDS_CSTAT_P3); u8 cstat = sii8620_readb(ctx, REG_TMDS_CSTAT_P3);
if (cstat & BIT_TMDS_CSTAT_P3_SCDT) if (cstat & BIT_TMDS_CSTAT_P3_SCDT) {
if (ctx->sink_type == SINK_HDMI)
/* enable infoframe interrupt */
sii8620_scdt_high(ctx); sii8620_scdt_high(ctx);
else
sii8620_start_video(ctx);
}
} }
sii8620_write(ctx, REG_INTR5, stat); sii8620_write(ctx, REG_INTR5, stat);
@ -2191,6 +2191,19 @@ static void sii8620_detach(struct drm_bridge *bridge)
rc_unregister_device(ctx->rc_dev); rc_unregister_device(ctx->rc_dev);
} }
static enum drm_mode_status sii8620_mode_valid(struct drm_bridge *bridge,
const struct drm_display_mode *mode)
{
struct sii8620 *ctx = bridge_to_sii8620(bridge);
bool can_pack = ctx->devcap[MHL_DCAP_VID_LINK_MODE] &
MHL_DCAP_VID_LINK_PPIXEL;
unsigned int max_pclk = sii8620_is_mhl3(ctx) ? MHL3_MAX_LCLK :
MHL1_MAX_LCLK;
max_pclk /= can_pack ? 2 : 3;
return (mode->clock > max_pclk) ? MODE_CLOCK_HIGH : MODE_OK;
}
static bool sii8620_mode_fixup(struct drm_bridge *bridge, static bool sii8620_mode_fixup(struct drm_bridge *bridge,
const struct drm_display_mode *mode, const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
@ -2220,8 +2233,9 @@ end:
union hdmi_infoframe frm; union hdmi_infoframe frm;
u8 mhl_vic[] = { 0, 95, 94, 93, 98 }; u8 mhl_vic[] = { 0, 95, 94, 93, 98 };
/* FIXME: We need the connector here */
drm_hdmi_vendor_infoframe_from_display_mode( drm_hdmi_vendor_infoframe_from_display_mode(
&frm.vendor.hdmi, adjusted_mode); &frm.vendor.hdmi, NULL, adjusted_mode);
vic = frm.vendor.hdmi.vic; vic = frm.vendor.hdmi.vic;
if (vic >= ARRAY_SIZE(mhl_vic)) if (vic >= ARRAY_SIZE(mhl_vic))
vic = 0; vic = 0;
@ -2238,6 +2252,7 @@ static const struct drm_bridge_funcs sii8620_bridge_funcs = {
.attach = sii8620_attach, .attach = sii8620_attach,
.detach = sii8620_detach, .detach = sii8620_detach,
.mode_fixup = sii8620_mode_fixup, .mode_fixup = sii8620_mode_fixup,
.mode_valid = sii8620_mode_valid,
}; };
static int sii8620_probe(struct i2c_client *client, static int sii8620_probe(struct i2c_client *client,

View File

@ -1438,7 +1438,9 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi,
u8 buffer[10]; u8 buffer[10];
ssize_t err; ssize_t err;
err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, mode); err = drm_hdmi_vendor_infoframe_from_display_mode(&frame,
&hdmi->connector,
mode);
if (err < 0) if (err < 0)
/* /*
* Going into that statement does not means vendor infoframe * Going into that statement does not means vendor infoframe
@ -1911,8 +1913,6 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid); cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid);
ret = drm_add_edid_modes(connector, edid); ret = drm_add_edid_modes(connector, edid);
/* Store the ELD */
drm_edid_to_eld(connector, edid);
kfree(edid); kfree(edid);
} else { } else {
dev_dbg(hdmi->dev, "failed to get edid\n"); dev_dbg(hdmi->dev, "failed to get edid\n");

View File

@ -6,6 +6,8 @@
* *
* Copyright (C) 2016 Pengutronix, Philipp Zabel <p.zabel@pengutronix.de> * Copyright (C) 2016 Pengutronix, Philipp Zabel <p.zabel@pengutronix.de>
* *
* Copyright (C) 2016 Zodiac Inflight Innovations
*
* Initially based on: drivers/gpu/drm/i2c/tda998x_drv.c * Initially based on: drivers/gpu/drm/i2c/tda998x_drv.c
* *
* Copyright (C) 2012 Texas Instruments * Copyright (C) 2012 Texas Instruments

View File

@ -13,6 +13,14 @@
#include "cirrus_drv.h" #include "cirrus_drv.h"
static int cirrus_create_handle(struct drm_framebuffer *fb,
struct drm_file* file_priv,
unsigned int* handle)
{
struct cirrus_framebuffer *cirrus_fb = to_cirrus_framebuffer(fb);
return drm_gem_handle_create(file_priv, cirrus_fb->obj, handle);
}
static void cirrus_user_framebuffer_destroy(struct drm_framebuffer *fb) static void cirrus_user_framebuffer_destroy(struct drm_framebuffer *fb)
{ {
@ -24,6 +32,7 @@ static void cirrus_user_framebuffer_destroy(struct drm_framebuffer *fb)
} }
static const struct drm_framebuffer_funcs cirrus_fb_funcs = { static const struct drm_framebuffer_funcs cirrus_fb_funcs = {
.create_handle = cirrus_create_handle,
.destroy = cirrus_user_framebuffer_destroy, .destroy = cirrus_user_framebuffer_destroy,
}; };

View File

@ -33,6 +33,7 @@
#include <linux/sync_file.h> #include <linux/sync_file.h>
#include "drm_crtc_internal.h" #include "drm_crtc_internal.h"
#include "drm_internal.h"
void __drm_crtc_commit_free(struct kref *kref) void __drm_crtc_commit_free(struct kref *kref)
{ {
@ -907,11 +908,12 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
state->src_h > fb_height || state->src_h > fb_height ||
state->src_y > fb_height - state->src_h) { state->src_y > fb_height - state->src_h) {
DRM_DEBUG_ATOMIC("Invalid source coordinates " DRM_DEBUG_ATOMIC("Invalid source coordinates "
"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n",
state->src_w >> 16, ((state->src_w & 0xffff) * 15625) >> 10, state->src_w >> 16, ((state->src_w & 0xffff) * 15625) >> 10,
state->src_h >> 16, ((state->src_h & 0xffff) * 15625) >> 10, state->src_h >> 16, ((state->src_h & 0xffff) * 15625) >> 10,
state->src_x >> 16, ((state->src_x & 0xffff) * 15625) >> 10, state->src_x >> 16, ((state->src_x & 0xffff) * 15625) >> 10,
state->src_y >> 16, ((state->src_y & 0xffff) * 15625) >> 10); state->src_y >> 16, ((state->src_y & 0xffff) * 15625) >> 10,
state->fb->width, state->fb->height);
return -ENOSPC; return -ENOSPC;
} }
@ -934,21 +936,8 @@ static void drm_atomic_plane_print_state(struct drm_printer *p,
drm_printf(p, "plane[%u]: %s\n", plane->base.id, plane->name); drm_printf(p, "plane[%u]: %s\n", plane->base.id, plane->name);
drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)"); drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
drm_printf(p, "\tfb=%u\n", state->fb ? state->fb->base.id : 0); drm_printf(p, "\tfb=%u\n", state->fb ? state->fb->base.id : 0);
if (state->fb) { if (state->fb)
struct drm_framebuffer *fb = state->fb; drm_framebuffer_print_info(p, 2, state->fb);
int i, n = fb->format->num_planes;
struct drm_format_name_buf format_name;
drm_printf(p, "\t\tformat=%s\n",
drm_get_format_name(fb->format->format, &format_name));
drm_printf(p, "\t\t\tmodifier=0x%llx\n", fb->modifier);
drm_printf(p, "\t\tsize=%dx%d\n", fb->width, fb->height);
drm_printf(p, "\t\tlayers:\n");
for (i = 0; i < n; i++) {
drm_printf(p, "\t\t\tpitch[%d]=%u\n", i, fb->pitches[i]);
drm_printf(p, "\t\t\toffset[%d]=%u\n", i, fb->offsets[i]);
}
}
drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest)); drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest));
drm_printf(p, "\tsrc-pos=" DRM_RECT_FP_FMT "\n", DRM_RECT_FP_ARG(&src)); drm_printf(p, "\tsrc-pos=" DRM_RECT_FP_FMT "\n", DRM_RECT_FP_ARG(&src));
drm_printf(p, "\trotation=%x\n", state->rotation); drm_printf(p, "\trotation=%x\n", state->rotation);
@ -1808,7 +1797,7 @@ int drm_atomic_debugfs_init(struct drm_minor *minor)
#endif #endif
/* /*
* The big monstor ioctl * The big monster ioctl
*/ */
static struct drm_pending_vblank_event *create_vblank_event( static struct drm_pending_vblank_event *create_vblank_event(

View File

@ -695,6 +695,100 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
} }
EXPORT_SYMBOL(drm_atomic_helper_check_modeset); EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
/**
* drm_atomic_helper_check_plane_state() - Check plane state for validity
* @plane_state: plane state to check
* @crtc_state: crtc state to check
* @clip: integer clipping coordinates
* @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
* @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
* @can_position: is it legal to position the plane such that it
* doesn't cover the entire crtc? This will generally
* only be false for primary planes.
* @can_update_disabled: can the plane be updated while the crtc
* is disabled?
*
* Checks that a desired plane update is valid, and updates various
* bits of derived state (clipped coordinates etc.). Drivers that provide
* their own plane handling rather than helper-provided implementations may
* still wish to call this function to avoid duplication of error checking
* code.
*
* RETURNS:
* Zero if update appears valid, error code on failure
*/
int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
const struct drm_crtc_state *crtc_state,
const struct drm_rect *clip,
int min_scale,
int max_scale,
bool can_position,
bool can_update_disabled)
{
struct drm_framebuffer *fb = plane_state->fb;
struct drm_rect *src = &plane_state->src;
struct drm_rect *dst = &plane_state->dst;
unsigned int rotation = plane_state->rotation;
int hscale, vscale;
WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc);
*src = drm_plane_state_src(plane_state);
*dst = drm_plane_state_dest(plane_state);
if (!fb) {
plane_state->visible = false;
return 0;
}
/* crtc should only be NULL when disabling (i.e., !fb) */
if (WARN_ON(!plane_state->crtc)) {
plane_state->visible = false;
return 0;
}
if (!crtc_state->enable && !can_update_disabled) {
DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n");
return -EINVAL;
}
drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
/* Check scaling */
hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
if (hscale < 0 || vscale < 0) {
DRM_DEBUG_KMS("Invalid scaling of plane\n");
drm_rect_debug_print("src: ", &plane_state->src, true);
drm_rect_debug_print("dst: ", &plane_state->dst, false);
return -ERANGE;
}
plane_state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation);
if (!plane_state->visible)
/*
* Plane isn't visible; some drivers can handle this
* so we just return success here. Drivers that can't
* (including those that use the primary plane helper's
* update function) will return an error from their
* update_plane handler.
*/
return 0;
if (!can_position && !drm_rect_equals(dst, clip)) {
DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
drm_rect_debug_print("dst: ", dst, false);
drm_rect_debug_print("clip: ", clip, false);
return -EINVAL;
}
return 0;
}
EXPORT_SYMBOL(drm_atomic_helper_check_plane_state);
/** /**
* drm_atomic_helper_check_planes - validate state object for planes changes * drm_atomic_helper_check_planes - validate state object for planes changes
* @dev: DRM device * @dev: DRM device
@ -907,6 +1001,12 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
* *
* Drivers can use this for building their own atomic commit if they don't have * Drivers can use this for building their own atomic commit if they don't have
* a pure helper-based modeset implementation. * a pure helper-based modeset implementation.
*
* Since these updates are not synchronized with lockings, only code paths
* called from &drm_mode_config_helper_funcs.atomic_commit_tail can look at the
* legacy state filled out by this helper. Defacto this means this helper and
* the legacy state pointers are only really useful for transitioning an
* existing driver to the atomic world.
*/ */
void void
drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
@ -1787,11 +1887,8 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
!try_wait_for_completion(&old_conn_state->commit->flip_done)) !try_wait_for_completion(&old_conn_state->commit->flip_done))
return -EBUSY; return -EBUSY;
/* commit tracked through new_crtc_state->commit, no need to do it explicitly */ /* Always track connectors explicitly for e.g. link retraining. */
if (new_conn_state->crtc) commit = crtc_or_fake_commit(state, new_conn_state->crtc ?: old_conn_state->crtc);
continue;
commit = crtc_or_fake_commit(state, old_conn_state->crtc);
if (!commit) if (!commit)
return -ENOMEM; return -ENOMEM;
@ -1805,10 +1902,7 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
!try_wait_for_completion(&old_plane_state->commit->flip_done)) !try_wait_for_completion(&old_plane_state->commit->flip_done))
return -EBUSY; return -EBUSY;
/* /* Always track planes explicitly for async pageflip support. */
* Unlike connectors, always track planes explicitly for
* async pageflip support.
*/
commit = crtc_or_fake_commit(state, new_plane_state->crtc ?: old_plane_state->crtc); commit = crtc_or_fake_commit(state, new_plane_state->crtc ?: old_plane_state->crtc);
if (!commit) if (!commit)
return -ENOMEM; return -ENOMEM;

View File

@ -158,6 +158,14 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id,
} }
} }
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
ret = drm_framebuffer_debugfs_init(minor);
if (ret) {
DRM_ERROR("Failed to create framebuffer debugfs file\n");
return ret;
}
}
if (dev->driver->debugfs_init) { if (dev->driver->debugfs_init) {
ret = dev->driver->debugfs_init(minor); ret = dev->driver->debugfs_init(minor);
if (ret) { if (ret) {

View File

@ -1097,7 +1097,6 @@ int drm_dp_aux_register(struct drm_dp_aux *aux)
aux->ddc.class = I2C_CLASS_DDC; aux->ddc.class = I2C_CLASS_DDC;
aux->ddc.owner = THIS_MODULE; aux->ddc.owner = THIS_MODULE;
aux->ddc.dev.parent = aux->dev; aux->ddc.dev.parent = aux->dev;
aux->ddc.dev.of_node = aux->dev->of_node;
strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev), strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev),
sizeof(aux->ddc.name)); sizeof(aux->ddc.name));

View File

@ -75,53 +75,6 @@ static bool drm_core_init_complete = false;
static struct dentry *drm_debugfs_root; static struct dentry *drm_debugfs_root;
#define DRM_PRINTK_FMT "[" DRM_NAME ":%s]%s %pV"
void drm_dev_printk(const struct device *dev, const char *level,
unsigned int category, const char *function_name,
const char *prefix, const char *format, ...)
{
struct va_format vaf;
va_list args;
if (category != DRM_UT_NONE && !(drm_debug & category))
return;
va_start(args, format);
vaf.fmt = format;
vaf.va = &args;
if (dev)
dev_printk(level, dev, DRM_PRINTK_FMT, function_name, prefix,
&vaf);
else
printk("%s" DRM_PRINTK_FMT, level, function_name, prefix, &vaf);
va_end(args);
}
EXPORT_SYMBOL(drm_dev_printk);
void drm_printk(const char *level, unsigned int category,
const char *format, ...)
{
struct va_format vaf;
va_list args;
if (category != DRM_UT_NONE && !(drm_debug & category))
return;
va_start(args, format);
vaf.fmt = format;
vaf.va = &args;
printk("%s" "[" DRM_NAME ":%ps]%s %pV",
level, __builtin_return_address(0),
strcmp(level, KERN_ERR) == 0 ? " *ERROR*" : "", &vaf);
va_end(args);
}
EXPORT_SYMBOL(drm_printk);
/* /*
* DRM Minors * DRM Minors
* A DRM device can provide several char-dev interfaces on the DRM-Major. Each * A DRM device can provide several char-dev interfaces on the DRM-Major. Each

View File

@ -3398,6 +3398,7 @@ static int
do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len, do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
const u8 *video_db, u8 video_len) const u8 *video_db, u8 video_len)
{ {
struct drm_display_info *info = &connector->display_info;
int modes = 0, offset = 0, i, multi_present = 0, multi_len; int modes = 0, offset = 0, i, multi_present = 0, multi_len;
u8 vic_len, hdmi_3d_len = 0; u8 vic_len, hdmi_3d_len = 0;
u16 mask; u16 mask;
@ -3525,6 +3526,8 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
} }
out: out:
if (modes > 0)
info->has_hdmi_infoframe = true;
return modes; return modes;
} }
@ -3761,8 +3764,8 @@ drm_parse_hdmi_vsdb_audio(struct drm_connector *connector, const u8 *db)
{ {
u8 len = cea_db_payload_len(db); u8 len = cea_db_payload_len(db);
if (len >= 6) if (len >= 6 && (db[6] & (1 << 7)))
connector->eld[5] |= (db[6] >> 7) << 1; /* Supports_AI */ connector->eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= DRM_ELD_SUPPORTS_AI;
if (len >= 8) { if (len >= 8) {
connector->latency_present[0] = db[8] >> 7; connector->latency_present[0] = db[8] >> 7;
connector->latency_present[1] = (db[8] >> 6) & 1; connector->latency_present[1] = (db[8] >> 6) & 1;
@ -3834,16 +3837,27 @@ void drm_edid_get_monitor_name(struct edid *edid, char *name, int bufsize)
} }
EXPORT_SYMBOL(drm_edid_get_monitor_name); EXPORT_SYMBOL(drm_edid_get_monitor_name);
/** static void clear_eld(struct drm_connector *connector)
{
memset(connector->eld, 0, sizeof(connector->eld));
connector->latency_present[0] = false;
connector->latency_present[1] = false;
connector->video_latency[0] = 0;
connector->audio_latency[0] = 0;
connector->video_latency[1] = 0;
connector->audio_latency[1] = 0;
}
/*
* drm_edid_to_eld - build ELD from EDID * drm_edid_to_eld - build ELD from EDID
* @connector: connector corresponding to the HDMI/DP sink * @connector: connector corresponding to the HDMI/DP sink
* @edid: EDID to parse * @edid: EDID to parse
* *
* Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. The * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. The
* Conn_Type, HDCP and Port_ID ELD fields are left for the graphics driver to * HDCP and Port_ID ELD fields are left for the graphics driver to fill in.
* fill in.
*/ */
void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) static void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
{ {
uint8_t *eld = connector->eld; uint8_t *eld = connector->eld;
u8 *cea; u8 *cea;
@ -3852,14 +3866,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
int mnl; int mnl;
int dbl; int dbl;
memset(eld, 0, sizeof(connector->eld)); clear_eld(connector);
connector->latency_present[0] = false;
connector->latency_present[1] = false;
connector->video_latency[0] = 0;
connector->audio_latency[0] = 0;
connector->video_latency[1] = 0;
connector->audio_latency[1] = 0;
if (!edid) if (!edid)
return; return;
@ -3870,17 +3877,18 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
return; return;
} }
mnl = get_monitor_name(edid, eld + 20); mnl = get_monitor_name(edid, &eld[DRM_ELD_MONITOR_NAME_STRING]);
DRM_DEBUG_KMS("ELD monitor %s\n", &eld[DRM_ELD_MONITOR_NAME_STRING]);
eld[4] = (cea[1] << 5) | mnl; eld[DRM_ELD_CEA_EDID_VER_MNL] = cea[1] << DRM_ELD_CEA_EDID_VER_SHIFT;
DRM_DEBUG_KMS("ELD monitor %s\n", eld + 20); eld[DRM_ELD_CEA_EDID_VER_MNL] |= mnl;
eld[0] = 2 << 3; /* ELD version: 2 */ eld[DRM_ELD_VER] = DRM_ELD_VER_CEA861D;
eld[16] = edid->mfg_id[0]; eld[DRM_ELD_MANUFACTURER_NAME0] = edid->mfg_id[0];
eld[17] = edid->mfg_id[1]; eld[DRM_ELD_MANUFACTURER_NAME1] = edid->mfg_id[1];
eld[18] = edid->prod_code[0]; eld[DRM_ELD_PRODUCT_CODE0] = edid->prod_code[0];
eld[19] = edid->prod_code[1]; eld[DRM_ELD_PRODUCT_CODE1] = edid->prod_code[1];
if (cea_revision(cea) >= 3) { if (cea_revision(cea) >= 3) {
int i, start, end; int i, start, end;
@ -3901,14 +3909,14 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
/* Audio Data Block, contains SADs */ /* Audio Data Block, contains SADs */
sad_count = min(dbl / 3, 15 - total_sad_count); sad_count = min(dbl / 3, 15 - total_sad_count);
if (sad_count >= 1) if (sad_count >= 1)
memcpy(eld + 20 + mnl + total_sad_count * 3, memcpy(&eld[DRM_ELD_CEA_SAD(mnl, total_sad_count)],
&db[1], sad_count * 3); &db[1], sad_count * 3);
total_sad_count += sad_count; total_sad_count += sad_count;
break; break;
case SPEAKER_BLOCK: case SPEAKER_BLOCK:
/* Speaker Allocation Data Block */ /* Speaker Allocation Data Block */
if (dbl >= 1) if (dbl >= 1)
eld[7] = db[1]; eld[DRM_ELD_SPEAKER] = db[1];
break; break;
case VENDOR_BLOCK: case VENDOR_BLOCK:
/* HDMI Vendor-Specific Data Block */ /* HDMI Vendor-Specific Data Block */
@ -3920,7 +3928,13 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
} }
} }
} }
eld[5] |= total_sad_count << 4; eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= total_sad_count << DRM_ELD_SAD_COUNT_SHIFT;
if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
connector->connector_type == DRM_MODE_CONNECTOR_eDP)
eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= DRM_ELD_CONN_TYPE_DP;
else
eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= DRM_ELD_CONN_TYPE_HDMI;
eld[DRM_ELD_BASELINE_ELD_LEN] = eld[DRM_ELD_BASELINE_ELD_LEN] =
DIV_ROUND_UP(drm_eld_calc_baseline_block_size(eld), 4); DIV_ROUND_UP(drm_eld_calc_baseline_block_size(eld), 4);
@ -3928,7 +3942,6 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", DRM_DEBUG_KMS("ELD size %d, SAD count %d\n",
drm_eld_size(eld), total_sad_count); drm_eld_size(eld), total_sad_count);
} }
EXPORT_SYMBOL(drm_edid_to_eld);
/** /**
* drm_edid_to_sad - extracts SADs from EDID * drm_edid_to_sad - extracts SADs from EDID
@ -4238,6 +4251,8 @@ static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
struct drm_display_info *display = &connector->display_info; struct drm_display_info *display = &connector->display_info;
struct drm_hdmi_info *hdmi = &display->hdmi; struct drm_hdmi_info *hdmi = &display->hdmi;
display->has_hdmi_infoframe = true;
if (hf_vsdb[6] & 0x80) { if (hf_vsdb[6] & 0x80) {
hdmi->scdc.supported = true; hdmi->scdc.supported = true;
if (hf_vsdb[6] & 0x40) if (hf_vsdb[6] & 0x40)
@ -4411,6 +4426,7 @@ static void drm_add_display_info(struct drm_connector *connector,
info->cea_rev = 0; info->cea_rev = 0;
info->max_tmds_clock = 0; info->max_tmds_clock = 0;
info->dvi_dual = false; info->dvi_dual = false;
info->has_hdmi_infoframe = false;
info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP); info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP);
@ -4608,8 +4624,8 @@ static int add_displayid_detailed_modes(struct drm_connector *connector,
* @edid: EDID data * @edid: EDID data
* *
* Add the specified modes to the connector's mode list. Also fills out the * Add the specified modes to the connector's mode list. Also fills out the
* &drm_display_info structure in @connector with any information which can be * &drm_display_info structure and ELD in @connector with any information which
* derived from the edid. * can be derived from the edid.
* *
* Return: The number of modes added or 0 if we couldn't find any. * Return: The number of modes added or 0 if we couldn't find any.
*/ */
@ -4619,9 +4635,11 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
u32 quirks; u32 quirks;
if (edid == NULL) { if (edid == NULL) {
clear_eld(connector);
return 0; return 0;
} }
if (!drm_edid_is_valid(edid)) { if (!drm_edid_is_valid(edid)) {
clear_eld(connector);
dev_warn(connector->dev->dev, "%s: EDID invalid.\n", dev_warn(connector->dev->dev, "%s: EDID invalid.\n",
connector->name); connector->name);
return 0; return 0;
@ -4629,6 +4647,8 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
quirks = edid_get_quirks(edid); quirks = edid_get_quirks(edid);
drm_edid_to_eld(connector, edid);
/* /*
* CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks. * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
* To avoid multiple parsing of same block, lets parse that map * To avoid multiple parsing of same block, lets parse that map
@ -4904,6 +4924,7 @@ s3d_structure_from_display_mode(const struct drm_display_mode *mode)
* drm_hdmi_vendor_infoframe_from_display_mode() - fill an HDMI infoframe with * drm_hdmi_vendor_infoframe_from_display_mode() - fill an HDMI infoframe with
* data from a DRM display mode * data from a DRM display mode
* @frame: HDMI vendor infoframe * @frame: HDMI vendor infoframe
* @connector: the connector
* @mode: DRM display mode * @mode: DRM display mode
* *
* Note that there's is a need to send HDMI vendor infoframes only when using a * Note that there's is a need to send HDMI vendor infoframes only when using a
@ -4914,8 +4935,15 @@ s3d_structure_from_display_mode(const struct drm_display_mode *mode)
*/ */
int int
drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
struct drm_connector *connector,
const struct drm_display_mode *mode) const struct drm_display_mode *mode)
{ {
/*
* FIXME: sil-sii8620 doesn't have a connector around when
* we need one, so we have to be prepared for a NULL connector.
*/
bool has_hdmi_infoframe = connector ?
connector->display_info.has_hdmi_infoframe : false;
int err; int err;
u32 s3d_flags; u32 s3d_flags;
u8 vic; u8 vic;
@ -4923,11 +4951,21 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
if (!frame || !mode) if (!frame || !mode)
return -EINVAL; return -EINVAL;
if (!has_hdmi_infoframe)
return -EINVAL;
vic = drm_match_hdmi_mode(mode); vic = drm_match_hdmi_mode(mode);
s3d_flags = mode->flags & DRM_MODE_FLAG_3D_MASK; s3d_flags = mode->flags & DRM_MODE_FLAG_3D_MASK;
if (!vic && !s3d_flags) /*
return -EINVAL; * Even if it's not absolutely necessary to send the infoframe
* (ie.vic==0 and s3d_struct==0) we will still send it if we
* know that the sink can handle it. This is based on a
* suggestion in HDMI 2.0 Appendix F. Apparently some sinks
* have trouble realizing that they shuld switch from 3D to 2D
* mode if the source simply stops sending the infoframe when
* it wants to switch from 3D to 2D.
*/
if (vic && s3d_flags) if (vic && s3d_flags)
return -EINVAL; return -EINVAL;
@ -4936,9 +4974,7 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
if (err < 0) if (err < 0)
return err; return err;
if (vic)
frame->vic = vic; frame->vic = vic;
else
frame->s3d_struct = s3d_structure_from_display_mode(mode); frame->s3d_struct = s3d_structure_from_display_mode(mode);
return 0; return 0;

View File

@ -130,43 +130,6 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
} }
EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr); EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);
#ifdef CONFIG_DEBUG_FS
static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m)
{
int i;
seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height,
(char *)&fb->format->format);
for (i = 0; i < fb->format->num_planes; i++) {
seq_printf(m, " %d: offset=%d pitch=%d, obj: ",
i, fb->offsets[i], fb->pitches[i]);
drm_gem_cma_describe(drm_fb_cma_get_gem_obj(fb, i), m);
}
}
/**
* drm_fb_cma_debugfs_show() - Helper to list CMA framebuffer objects
* in debugfs.
* @m: output file
* @arg: private data for the callback
*/
int drm_fb_cma_debugfs_show(struct seq_file *m, void *arg)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
struct drm_framebuffer *fb;
mutex_lock(&dev->mode_config.fb_lock);
drm_for_each_fb(fb, dev)
drm_fb_cma_describe(fb, m);
mutex_unlock(&dev->mode_config.fb_lock);
return 0;
}
EXPORT_SYMBOL_GPL(drm_fb_cma_debugfs_show);
#endif
static int drm_fb_cma_mmap(struct fb_info *info, struct vm_area_struct *vma) static int drm_fb_cma_mmap(struct fb_info *info, struct vm_area_struct *vma)
{ {
return dma_mmap_writecombine(info->device, vma, info->screen_base, return dma_mmap_writecombine(info->device, vma, info->screen_base,

View File

@ -150,6 +150,9 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
{ {
int err; int err;
if (!fb_helper)
return 0;
mutex_lock(&fb_helper->lock); mutex_lock(&fb_helper->lock);
err = __drm_fb_helper_add_one_connector(fb_helper, connector); err = __drm_fb_helper_add_one_connector(fb_helper, connector);
mutex_unlock(&fb_helper->lock); mutex_unlock(&fb_helper->lock);
@ -161,7 +164,7 @@ EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
/** /**
* drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev
* emulation helper * emulation helper
* @fb_helper: fbdev initialized with drm_fb_helper_init * @fb_helper: fbdev initialized with drm_fb_helper_init, can be NULL
* *
* This functions adds all the available connectors for use with the given * This functions adds all the available connectors for use with the given
* fb_helper. This is a separate step to allow drivers to freely assign * fb_helper. This is a separate step to allow drivers to freely assign
@ -179,7 +182,7 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
struct drm_connector_list_iter conn_iter; struct drm_connector_list_iter conn_iter;
int i, ret = 0; int i, ret = 0;
if (!drm_fbdev_emulation) if (!drm_fbdev_emulation || !fb_helper)
return 0; return 0;
mutex_lock(&fb_helper->lock); mutex_lock(&fb_helper->lock);
@ -245,6 +248,9 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
{ {
int err; int err;
if (!fb_helper)
return 0;
mutex_lock(&fb_helper->lock); mutex_lock(&fb_helper->lock);
err = __drm_fb_helper_remove_one_connector(fb_helper, connector); err = __drm_fb_helper_remove_one_connector(fb_helper, connector);
mutex_unlock(&fb_helper->lock); mutex_unlock(&fb_helper->lock);
@ -484,7 +490,7 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
/** /**
* drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
* @fb_helper: fbcon to restore * @fb_helper: driver-allocated fbdev helper, can be NULL
* *
* This should be called from driver's drm &drm_driver.lastclose callback * This should be called from driver's drm &drm_driver.lastclose callback
* when implementing an fbcon on top of kms using this helper. This ensures that * when implementing an fbcon on top of kms using this helper. This ensures that
@ -498,7 +504,7 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
bool do_delayed; bool do_delayed;
int ret; int ret;
if (!drm_fbdev_emulation) if (!drm_fbdev_emulation || !fb_helper)
return -ENODEV; return -ENODEV;
if (READ_ONCE(fb_helper->deferred_setup)) if (READ_ONCE(fb_helper->deferred_setup))
@ -793,8 +799,10 @@ int drm_fb_helper_init(struct drm_device *dev,
struct drm_mode_config *config = &dev->mode_config; struct drm_mode_config *config = &dev->mode_config;
int i; int i;
if (!drm_fbdev_emulation) if (!drm_fbdev_emulation) {
dev->fb_helper = fb_helper;
return 0; return 0;
}
if (!max_conn_count) if (!max_conn_count)
return -EINVAL; return -EINVAL;
@ -829,6 +837,8 @@ int drm_fb_helper_init(struct drm_device *dev,
i++; i++;
} }
dev->fb_helper = fb_helper;
return 0; return 0;
out_free: out_free:
drm_fb_helper_crtc_free(fb_helper); drm_fb_helper_crtc_free(fb_helper);
@ -883,7 +893,7 @@ EXPORT_SYMBOL(drm_fb_helper_alloc_fbi);
/** /**
* drm_fb_helper_unregister_fbi - unregister fb_info framebuffer device * drm_fb_helper_unregister_fbi - unregister fb_info framebuffer device
* @fb_helper: driver-allocated fbdev helper * @fb_helper: driver-allocated fbdev helper, can be NULL
* *
* A wrapper around unregister_framebuffer, to release the fb_info * A wrapper around unregister_framebuffer, to release the fb_info
* framebuffer device. This must be called before releasing all resources for * framebuffer device. This must be called before releasing all resources for
@ -898,7 +908,7 @@ EXPORT_SYMBOL(drm_fb_helper_unregister_fbi);
/** /**
* drm_fb_helper_fini - finialize a &struct drm_fb_helper * drm_fb_helper_fini - finialize a &struct drm_fb_helper
* @fb_helper: driver-allocated fbdev helper * @fb_helper: driver-allocated fbdev helper, can be NULL
* *
* This cleans up all remaining resources associated with @fb_helper. Must be * This cleans up all remaining resources associated with @fb_helper. Must be
* called after drm_fb_helper_unlink_fbi() was called. * called after drm_fb_helper_unlink_fbi() was called.
@ -907,7 +917,12 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
{ {
struct fb_info *info; struct fb_info *info;
if (!drm_fbdev_emulation || !fb_helper) if (!fb_helper)
return;
fb_helper->dev->fb_helper = NULL;
if (!drm_fbdev_emulation)
return; return;
cancel_work_sync(&fb_helper->resume_work); cancel_work_sync(&fb_helper->resume_work);
@ -937,7 +952,7 @@ EXPORT_SYMBOL(drm_fb_helper_fini);
/** /**
* drm_fb_helper_unlink_fbi - wrapper around unlink_framebuffer * drm_fb_helper_unlink_fbi - wrapper around unlink_framebuffer
* @fb_helper: driver-allocated fbdev helper * @fb_helper: driver-allocated fbdev helper, can be NULL
* *
* A wrapper around unlink_framebuffer implemented by fbdev core * A wrapper around unlink_framebuffer implemented by fbdev core
*/ */
@ -1138,7 +1153,7 @@ EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit);
/** /**
* drm_fb_helper_set_suspend - wrapper around fb_set_suspend * drm_fb_helper_set_suspend - wrapper around fb_set_suspend
* @fb_helper: driver-allocated fbdev helper * @fb_helper: driver-allocated fbdev helper, can be NULL
* @suspend: whether to suspend or resume * @suspend: whether to suspend or resume
* *
* A wrapper around fb_set_suspend implemented by fbdev core. * A wrapper around fb_set_suspend implemented by fbdev core.
@ -1155,7 +1170,7 @@ EXPORT_SYMBOL(drm_fb_helper_set_suspend);
/** /**
* drm_fb_helper_set_suspend_unlocked - wrapper around fb_set_suspend that also * drm_fb_helper_set_suspend_unlocked - wrapper around fb_set_suspend that also
* takes the console lock * takes the console lock
* @fb_helper: driver-allocated fbdev helper * @fb_helper: driver-allocated fbdev helper, can be NULL
* @suspend: whether to suspend or resume * @suspend: whether to suspend or resume
* *
* A wrapper around fb_set_suspend() that takes the console lock. If the lock * A wrapper around fb_set_suspend() that takes the console lock. If the lock
@ -2576,7 +2591,7 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config);
/** /**
* drm_fb_helper_hotplug_event - respond to a hotplug notification by * drm_fb_helper_hotplug_event - respond to a hotplug notification by
* probing all the outputs attached to the fb * probing all the outputs attached to the fb
* @fb_helper: the drm_fb_helper * @fb_helper: driver-allocated fbdev helper, can be NULL
* *
* Scan the connectors attached to the fb_helper and try to put together a * Scan the connectors attached to the fb_helper and try to put together a
* setup after notification of a change in output configuration. * setup after notification of a change in output configuration.
@ -2598,7 +2613,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
{ {
int err = 0; int err = 0;
if (!drm_fbdev_emulation) if (!drm_fbdev_emulation || !fb_helper)
return 0; return 0;
mutex_lock(&fb_helper->lock); mutex_lock(&fb_helper->lock);
@ -2626,6 +2641,34 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
} }
EXPORT_SYMBOL(drm_fb_helper_hotplug_event); EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
/**
* drm_fb_helper_lastclose - DRM driver lastclose helper for fbdev emulation
* @dev: DRM device
*
* This function can be used as the &drm_driver->lastclose callback for drivers
* that only need to call drm_fb_helper_restore_fbdev_mode_unlocked().
*/
void drm_fb_helper_lastclose(struct drm_device *dev)
{
drm_fb_helper_restore_fbdev_mode_unlocked(dev->fb_helper);
}
EXPORT_SYMBOL(drm_fb_helper_lastclose);
/**
* drm_fb_helper_output_poll_changed - DRM mode config \.output_poll_changed
* helper for fbdev emulation
* @dev: DRM device
*
* This function can be used as the
* &drm_mode_config_funcs.output_poll_changed callback for drivers that only
* need to call drm_fb_helper_hotplug_event().
*/
void drm_fb_helper_output_poll_changed(struct drm_device *dev)
{
drm_fb_helper_hotplug_event(dev->fb_helper);
}
EXPORT_SYMBOL(drm_fb_helper_output_poll_changed);
/* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT) /* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT)
* but the module doesn't depend on any fb console symbols. At least * but the module doesn't depend on any fb console symbols. At least
* attempt to load fbcon to avoid leaving the system without a usable console. * attempt to load fbcon to avoid leaving the system without a usable console.

View File

@ -25,7 +25,9 @@
#include <drm/drm_auth.h> #include <drm/drm_auth.h>
#include <drm/drm_framebuffer.h> #include <drm/drm_framebuffer.h>
#include <drm/drm_atomic.h> #include <drm/drm_atomic.h>
#include <drm/drm_print.h>
#include "drm_internal.h"
#include "drm_crtc_internal.h" #include "drm_crtc_internal.h"
/** /**
@ -78,11 +80,12 @@ int drm_framebuffer_check_src_coords(uint32_t src_x, uint32_t src_y,
src_h > fb_height || src_h > fb_height ||
src_y > fb_height - src_h) { src_y > fb_height - src_h) {
DRM_DEBUG_KMS("Invalid source coordinates " DRM_DEBUG_KMS("Invalid source coordinates "
"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n",
src_w >> 16, ((src_w & 0xffff) * 15625) >> 10, src_w >> 16, ((src_w & 0xffff) * 15625) >> 10,
src_h >> 16, ((src_h & 0xffff) * 15625) >> 10, src_h >> 16, ((src_h & 0xffff) * 15625) >> 10,
src_x >> 16, ((src_x & 0xffff) * 15625) >> 10, src_x >> 16, ((src_x & 0xffff) * 15625) >> 10,
src_y >> 16, ((src_y & 0xffff) * 15625) >> 10); src_y >> 16, ((src_y & 0xffff) * 15625) >> 10,
fb->width, fb->height);
return -ENOSPC; return -ENOSPC;
} }
@ -766,14 +769,18 @@ static int atomic_remove_fb(struct drm_framebuffer *fb)
struct drm_plane *plane; struct drm_plane *plane;
struct drm_connector *conn; struct drm_connector *conn;
struct drm_connector_state *conn_state; struct drm_connector_state *conn_state;
int i, ret = 0; int i, ret;
unsigned plane_mask; unsigned plane_mask;
bool disable_crtcs = false;
retry_disable:
drm_modeset_acquire_init(&ctx, 0);
state = drm_atomic_state_alloc(dev); state = drm_atomic_state_alloc(dev);
if (!state) if (!state) {
return -ENOMEM; ret = -ENOMEM;
goto out;
drm_modeset_acquire_init(&ctx, 0); }
state->acquire_ctx = &ctx; state->acquire_ctx = &ctx;
retry: retry:
@ -794,7 +801,7 @@ retry:
goto unlock; goto unlock;
} }
if (plane_state->crtc->primary == plane) { if (disable_crtcs && plane_state->crtc->primary == plane) {
struct drm_crtc_state *crtc_state; struct drm_crtc_state *crtc_state;
crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc); crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc);
@ -819,6 +826,7 @@ retry:
plane->old_fb = plane->fb; plane->old_fb = plane->fb;
} }
/* This list is only filled when disable_crtcs is set. */
for_each_new_connector_in_state(state, conn, conn_state, i) { for_each_new_connector_in_state(state, conn, conn_state, i) {
ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
@ -841,9 +849,15 @@ unlock:
drm_atomic_state_put(state); drm_atomic_state_put(state);
out:
drm_modeset_drop_locks(&ctx); drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx); drm_modeset_acquire_fini(&ctx);
if (ret == -EINVAL && !disable_crtcs) {
disable_crtcs = true;
goto retry_disable;
}
return ret; return ret;
} }
@ -957,3 +971,60 @@ int drm_framebuffer_plane_height(int height,
return fb_plane_height(height, fb->format, plane); return fb_plane_height(height, fb->format, plane);
} }
EXPORT_SYMBOL(drm_framebuffer_plane_height); EXPORT_SYMBOL(drm_framebuffer_plane_height);
void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent,
const struct drm_framebuffer *fb)
{
struct drm_format_name_buf format_name;
unsigned int i;
drm_printf_indent(p, indent, "refcount=%u\n",
drm_framebuffer_read_refcount(fb));
drm_printf_indent(p, indent, "format=%s\n",
drm_get_format_name(fb->format->format, &format_name));
drm_printf_indent(p, indent, "modifier=0x%llx\n", fb->modifier);
drm_printf_indent(p, indent, "size=%ux%u\n", fb->width, fb->height);
drm_printf_indent(p, indent, "layers:\n");
for (i = 0; i < fb->format->num_planes; i++) {
drm_printf_indent(p, indent + 1, "size[%u]=%dx%d\n", i,
drm_framebuffer_plane_width(fb->width, fb, i),
drm_framebuffer_plane_height(fb->height, fb, i));
drm_printf_indent(p, indent + 1, "pitch[%u]=%u\n", i, fb->pitches[i]);
drm_printf_indent(p, indent + 1, "offset[%u]=%u\n", i, fb->offsets[i]);
drm_printf_indent(p, indent + 1, "obj[%u]:%s\n", i,
fb->obj[i] ? "" : "(null)");
if (fb->obj[i])
drm_gem_print_info(p, indent + 2, fb->obj[i]);
}
}
#ifdef CONFIG_DEBUG_FS
static int drm_framebuffer_info(struct seq_file *m, void *data)
{
struct drm_info_node *node = m->private;
struct drm_device *dev = node->minor->dev;
struct drm_printer p = drm_seq_file_printer(m);
struct drm_framebuffer *fb;
mutex_lock(&dev->mode_config.fb_lock);
drm_for_each_fb(fb, dev) {
drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
drm_framebuffer_print_info(&p, 1, fb);
}
mutex_unlock(&dev->mode_config.fb_lock);
return 0;
}
static const struct drm_info_list drm_framebuffer_debugfs_list[] = {
{ "framebuffer", drm_framebuffer_info, 0 },
};
int drm_framebuffer_debugfs_init(struct drm_minor *minor)
{
return drm_debugfs_create_files(drm_framebuffer_debugfs_list,
ARRAY_SIZE(drm_framebuffer_debugfs_list),
minor->debugfs_root, minor);
}
#endif

View File

@ -40,6 +40,7 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_vma_manager.h> #include <drm/drm_vma_manager.h>
#include <drm/drm_gem.h> #include <drm/drm_gem.h>
#include <drm/drm_print.h>
#include "drm_internal.h" #include "drm_internal.h"
/** @file drm_gem.c /** @file drm_gem.c
@ -1040,3 +1041,19 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
return ret; return ret;
} }
EXPORT_SYMBOL(drm_gem_mmap); EXPORT_SYMBOL(drm_gem_mmap);
void drm_gem_print_info(struct drm_printer *p, unsigned int indent,
const struct drm_gem_object *obj)
{
drm_printf_indent(p, indent, "name=%d\n", obj->name);
drm_printf_indent(p, indent, "refcount=%u\n",
kref_read(&obj->refcount));
drm_printf_indent(p, indent, "start=%08lx\n",
drm_vma_node_start(&obj->vma_node));
drm_printf_indent(p, indent, "size=%zu\n", obj->size);
drm_printf_indent(p, indent, "imported=%s\n",
obj->import_attach ? "yes" : "no");
if (obj->dev->driver->gem_print_info)
obj->dev->driver->gem_print_info(p, indent, obj);
}

View File

@ -397,31 +397,24 @@ unsigned long drm_gem_cma_get_unmapped_area(struct file *filp,
EXPORT_SYMBOL_GPL(drm_gem_cma_get_unmapped_area); EXPORT_SYMBOL_GPL(drm_gem_cma_get_unmapped_area);
#endif #endif
#ifdef CONFIG_DEBUG_FS
/** /**
* drm_gem_cma_describe - describe a CMA GEM object for debugfs * drm_gem_cma_print_info() - Print &drm_gem_cma_object info for debugfs
* @cma_obj: CMA GEM object * @p: DRM printer
* @m: debugfs file handle * @indent: Tab indentation level
* @obj: GEM object
* *
* This function can be used to dump a human-readable representation of the * This function can be used as the &drm_driver->gem_print_info callback.
* CMA GEM object into a synthetic file. * It prints paddr and vaddr for use in e.g. debugfs output.
*/ */
void drm_gem_cma_describe(struct drm_gem_cma_object *cma_obj, void drm_gem_cma_print_info(struct drm_printer *p, unsigned int indent,
struct seq_file *m) const struct drm_gem_object *obj)
{ {
struct drm_gem_object *obj = &cma_obj->base; const struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
uint64_t off;
off = drm_vma_node_start(&obj->vma_node); drm_printf_indent(p, indent, "paddr=%pad\n", &cma_obj->paddr);
drm_printf_indent(p, indent, "vaddr=%p\n", cma_obj->vaddr);
seq_printf(m, "%2d (%2d) %08llx %pad %p %zu",
obj->name, kref_read(&obj->refcount),
off, &cma_obj->paddr, cma_obj->vaddr, obj->size);
seq_printf(m, "\n");
} }
EXPORT_SYMBOL_GPL(drm_gem_cma_describe); EXPORT_SYMBOL(drm_gem_cma_print_info);
#endif
/** /**
* drm_gem_cma_prime_get_sg_table - provide a scatter/gather table of pinned * drm_gem_cma_prime_get_sg_table - provide a scatter/gather table of pinned
@ -482,9 +475,27 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev,
{ {
struct drm_gem_cma_object *cma_obj; struct drm_gem_cma_object *cma_obj;
if (sgt->nents != 1) if (sgt->nents != 1) {
/* check if the entries in the sg_table are contiguous */
dma_addr_t next_addr = sg_dma_address(sgt->sgl);
struct scatterlist *s;
unsigned int i;
for_each_sg(sgt->sgl, s, sgt->nents, i) {
/*
* sg_dma_address(s) is only valid for entries
* that have sg_dma_len(s) != 0
*/
if (!sg_dma_len(s))
continue;
if (sg_dma_address(s) != next_addr)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
next_addr = sg_dma_address(s) + sg_dma_len(s);
}
}
/* Create a CMA GEM buffer. */ /* Create a CMA GEM buffer. */
cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size); cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size);
if (IS_ERR(cma_obj)) if (IS_ERR(cma_obj))

View File

@ -111,6 +111,8 @@ int drm_gem_open_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
void drm_gem_open(struct drm_device *dev, struct drm_file *file_private); void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
void drm_gem_release(struct drm_device *dev, struct drm_file *file_private); void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);
void drm_gem_print_info(struct drm_printer *p, unsigned int indent,
const struct drm_gem_object *obj);
/* drm_debugfs.c drm_debugfs_crc.c */ /* drm_debugfs.c drm_debugfs_crc.c */
#if defined(CONFIG_DEBUG_FS) #if defined(CONFIG_DEBUG_FS)
@ -178,3 +180,8 @@ int drm_syncobj_reset_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_private); struct drm_file *file_private);
int drm_syncobj_signal_ioctl(struct drm_device *dev, void *data, int drm_syncobj_signal_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_private); struct drm_file *file_private);
/* drm_framebuffer.c */
void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent,
const struct drm_framebuffer *fb);
int drm_framebuffer_debugfs_init(struct drm_minor *minor);

View File

@ -92,7 +92,7 @@
* some basic allocator dumpers for debugging. * some basic allocator dumpers for debugging.
* *
* Note that this range allocator is not thread-safe, drivers need to protect * Note that this range allocator is not thread-safe, drivers need to protect
* modifications with their on locking. The idea behind this is that for a full * modifications with their own locking. The idea behind this is that for a full
* memory manager additional data needs to be protected anyway, hence internal * memory manager additional data needs to be protected anyway, hence internal
* locking would be fully redundant. * locking would be fully redundant.
*/ */

View File

@ -99,97 +99,6 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,
return count; return count;
} }
/**
* drm_plane_helper_check_state() - Check plane state for validity
* @state: plane state to check
* @clip: integer clipping coordinates
* @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
* @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
* @can_position: is it legal to position the plane such that it
* doesn't cover the entire crtc? This will generally
* only be false for primary planes.
* @can_update_disabled: can the plane be updated while the crtc
* is disabled?
*
* Checks that a desired plane update is valid, and updates various
* bits of derived state (clipped coordinates etc.). Drivers that provide
* their own plane handling rather than helper-provided implementations may
* still wish to call this function to avoid duplication of error checking
* code.
*
* RETURNS:
* Zero if update appears valid, error code on failure
*/
int drm_plane_helper_check_state(struct drm_plane_state *state,
const struct drm_rect *clip,
int min_scale,
int max_scale,
bool can_position,
bool can_update_disabled)
{
struct drm_crtc *crtc = state->crtc;
struct drm_framebuffer *fb = state->fb;
struct drm_rect *src = &state->src;
struct drm_rect *dst = &state->dst;
unsigned int rotation = state->rotation;
int hscale, vscale;
*src = drm_plane_state_src(state);
*dst = drm_plane_state_dest(state);
if (!fb) {
state->visible = false;
return 0;
}
/* crtc should only be NULL when disabling (i.e., !fb) */
if (WARN_ON(!crtc)) {
state->visible = false;
return 0;
}
if (!crtc->enabled && !can_update_disabled) {
DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n");
return -EINVAL;
}
drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
/* Check scaling */
hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
if (hscale < 0 || vscale < 0) {
DRM_DEBUG_KMS("Invalid scaling of plane\n");
drm_rect_debug_print("src: ", &state->src, true);
drm_rect_debug_print("dst: ", &state->dst, false);
return -ERANGE;
}
state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation);
if (!state->visible)
/*
* Plane isn't visible; some drivers can handle this
* so we just return success here. Drivers that can't
* (including those that use the primary plane helper's
* update function) will return an error from their
* update_plane handler.
*/
return 0;
if (!can_position && !drm_rect_equals(dst, clip)) {
DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
drm_rect_debug_print("dst: ", dst, false);
drm_rect_debug_print("clip: ", clip, false);
return -EINVAL;
}
return 0;
}
EXPORT_SYMBOL(drm_plane_helper_check_state);
/** /**
* drm_plane_helper_check_update() - Check plane update for validity * drm_plane_helper_check_update() - Check plane update for validity
* @plane: plane object to update * @plane: plane object to update
@ -230,7 +139,7 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
bool can_update_disabled, bool can_update_disabled,
bool *visible) bool *visible)
{ {
struct drm_plane_state state = { struct drm_plane_state plane_state = {
.plane = plane, .plane = plane,
.crtc = crtc, .crtc = crtc,
.fb = fb, .fb = fb,
@ -245,18 +154,22 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
.rotation = rotation, .rotation = rotation,
.visible = *visible, .visible = *visible,
}; };
struct drm_crtc_state crtc_state = {
.crtc = crtc,
.enable = crtc->enabled,
};
int ret; int ret;
ret = drm_plane_helper_check_state(&state, clip, ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
min_scale, max_scale, clip, min_scale, max_scale,
can_position, can_position,
can_update_disabled); can_update_disabled);
if (ret) if (ret)
return ret; return ret;
*src = state.src; *src = plane_state.src;
*dst = state.dst; *dst = plane_state.dst;
*visible = state.visible; *visible = plane_state.visible;
return 0; return 0;
} }

View File

@ -23,6 +23,8 @@
* Rob Clark <robdclark@gmail.com> * Rob Clark <robdclark@gmail.com>
*/ */
#define DEBUG /* for pr_debug() */
#include <stdarg.h> #include <stdarg.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <drm/drmP.h> #include <drm/drmP.h>
@ -53,13 +55,57 @@ EXPORT_SYMBOL(__drm_printfn_debug);
*/ */
void drm_printf(struct drm_printer *p, const char *f, ...) void drm_printf(struct drm_printer *p, const char *f, ...)
{ {
struct va_format vaf;
va_list args; va_list args;
va_start(args, f); va_start(args, f);
vaf.fmt = f; drm_vprintf(p, f, &args);
vaf.va = &args;
p->printfn(p, &vaf);
va_end(args); va_end(args);
} }
EXPORT_SYMBOL(drm_printf); EXPORT_SYMBOL(drm_printf);
#define DRM_PRINTK_FMT "[" DRM_NAME ":%s]%s %pV"
void drm_dev_printk(const struct device *dev, const char *level,
unsigned int category, const char *function_name,
const char *prefix, const char *format, ...)
{
struct va_format vaf;
va_list args;
if (category != DRM_UT_NONE && !(drm_debug & category))
return;
va_start(args, format);
vaf.fmt = format;
vaf.va = &args;
if (dev)
dev_printk(level, dev, DRM_PRINTK_FMT, function_name, prefix,
&vaf);
else
printk("%s" DRM_PRINTK_FMT, level, function_name, prefix, &vaf);
va_end(args);
}
EXPORT_SYMBOL(drm_dev_printk);
void drm_printk(const char *level, unsigned int category,
const char *format, ...)
{
struct va_format vaf;
va_list args;
if (category != DRM_UT_NONE && !(drm_debug & category))
return;
va_start(args, format);
vaf.fmt = format;
vaf.va = &args;
printk("%s" "[" DRM_NAME ":%ps]%s %pV",
level, __builtin_return_address(0),
strcmp(level, KERN_ERR) == 0 ? " *ERROR*" : "", &vaf);
va_end(args);
}
EXPORT_SYMBOL(drm_printk);

View File

@ -103,7 +103,8 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.x2 = crtc_state->adjusted_mode.hdisplay;
clip.y2 = crtc_state->adjusted_mode.vdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay;
ret = drm_plane_helper_check_state(plane_state, &clip, ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
&clip,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
false, true); false, true);

View File

@ -106,7 +106,8 @@ static int drm_syncobj_fence_get_or_add_callback(struct drm_syncobj *syncobj,
* callback when a fence has already been set. * callback when a fence has already been set.
*/ */
if (syncobj->fence) { if (syncobj->fence) {
*fence = dma_fence_get(syncobj->fence); *fence = dma_fence_get(rcu_dereference_protected(syncobj->fence,
lockdep_is_held(&syncobj->lock)));
ret = 1; ret = 1;
} else { } else {
*fence = NULL; *fence = NULL;
@ -168,8 +169,9 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
spin_lock(&syncobj->lock); spin_lock(&syncobj->lock);
old_fence = syncobj->fence; old_fence = rcu_dereference_protected(syncobj->fence,
syncobj->fence = fence; lockdep_is_held(&syncobj->lock));
rcu_assign_pointer(syncobj->fence, fence);
if (fence != old_fence) { if (fence != old_fence) {
list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) { list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) {
@ -659,7 +661,8 @@ static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj,
container_of(cb, struct syncobj_wait_entry, syncobj_cb); container_of(cb, struct syncobj_wait_entry, syncobj_cb);
/* This happens inside the syncobj lock */ /* This happens inside the syncobj lock */
wait->fence = dma_fence_get(syncobj->fence); wait->fence = dma_fence_get(rcu_dereference_protected(syncobj->fence,
lockdep_is_held(&syncobj->lock)));
wake_up_process(wait->task); wake_up_process(wait->task);
} }

View File

@ -663,14 +663,16 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
delta_ns = div_s64(1000000LL * (vpos * mode->crtc_htotal + hpos), delta_ns = div_s64(1000000LL * (vpos * mode->crtc_htotal + hpos),
mode->crtc_clock); mode->crtc_clock);
/* save this only for debugging purposes */
ts_etime = ktime_to_timespec64(etime);
ts_vblank_time = ktime_to_timespec64(*vblank_time);
/* Subtract time delta from raw timestamp to get final /* Subtract time delta from raw timestamp to get final
* vblank_time timestamp for end of vblank. * vblank_time timestamp for end of vblank.
*/ */
etime = ktime_sub_ns(etime, delta_ns); *vblank_time = ktime_sub_ns(etime, delta_ns);
*vblank_time = etime;
if ((drm_debug & DRM_UT_VBL) == 0)
return true;
ts_etime = ktime_to_timespec64(etime);
ts_vblank_time = ktime_to_timespec64(*vblank_time);
DRM_DEBUG_VBL("crtc %u : v p(%d,%d)@ %lld.%06ld -> %lld.%06ld [e %d us, %d rep]\n", DRM_DEBUG_VBL("crtc %u : v p(%d,%d)@ %lld.%06ld -> %lld.%06ld [e %d us, %d rep]\n",
pipe, hpos, vpos, pipe, hpos, vpos,

View File

@ -203,21 +203,16 @@ EXPORT_SYMBOL(drm_vma_offset_lookup_locked);
int drm_vma_offset_add(struct drm_vma_offset_manager *mgr, int drm_vma_offset_add(struct drm_vma_offset_manager *mgr,
struct drm_vma_offset_node *node, unsigned long pages) struct drm_vma_offset_node *node, unsigned long pages)
{ {
int ret; int ret = 0;
write_lock(&mgr->vm_lock); write_lock(&mgr->vm_lock);
if (drm_mm_node_allocated(&node->vm_node)) { if (!drm_mm_node_allocated(&node->vm_node))
ret = 0; ret = drm_mm_insert_node(&mgr->vm_addr_space_mm,
goto out_unlock; &node->vm_node, pages);
}
ret = drm_mm_insert_node(&mgr->vm_addr_space_mm, &node->vm_node, pages);
if (ret)
goto out_unlock;
out_unlock:
write_unlock(&mgr->vm_lock); write_unlock(&mgr->vm_lock);
return ret; return ret;
} }
EXPORT_SYMBOL(drm_vma_offset_add); EXPORT_SYMBOL(drm_vma_offset_add);

View File

@ -829,7 +829,8 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata)
DRM_INFO("%s: invalid AVI infoframe (%d)\n", __func__, ret); DRM_INFO("%s: invalid AVI infoframe (%d)\n", __func__, ret);
} }
ret = drm_hdmi_vendor_infoframe_from_display_mode(&frm.vendor.hdmi, m); ret = drm_hdmi_vendor_infoframe_from_display_mode(&frm.vendor.hdmi,
&hdata->connector, m);
if (!ret) if (!ret)
ret = hdmi_vendor_infoframe_pack(&frm.vendor.hdmi, buf, ret = hdmi_vendor_infoframe_pack(&frm.vendor.hdmi, buf,
sizeof(buf)); sizeof(buf));

View File

@ -395,7 +395,7 @@ static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
psb_mmu_clflush(pd->driver, (void *)&v[pt->index]); psb_mmu_clflush(pd->driver, (void *)&v[pt->index]);
atomic_set(&pd->driver->needs_tlbflush, 1); atomic_set(&pd->driver->needs_tlbflush, 1);
} }
kunmap_atomic(pt->v); kunmap_atomic(v);
spin_unlock(&pd->driver->lock); spin_unlock(&pd->driver->lock);
psb_mmu_free_pt(pt); psb_mmu_free_pt(pt);
return; return;

View File

@ -527,4 +527,4 @@ module_exit(psb_exit);
MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE); MODULE_LICENSE("GPL");

View File

@ -36,7 +36,6 @@
#include "mmu.h" #include "mmu.h"
#define DRIVER_AUTHOR "Alan Cox <alan@linux.intel.com> and others" #define DRIVER_AUTHOR "Alan Cox <alan@linux.intel.com> and others"
#define DRIVER_LICENSE "GPL"
#define DRIVER_NAME "gma500" #define DRIVER_NAME "gma500"
#define DRIVER_DESC "DRM driver for the Intel GMA500, GMA600, GMA3600, GMA3650" #define DRIVER_DESC "DRM driver for the Intel GMA500, GMA600, GMA3600, GMA3650"

View File

@ -1100,7 +1100,6 @@ static int tda998x_connector_get_modes(struct drm_connector *connector)
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
n = drm_add_edid_modes(connector, edid); n = drm_add_edid_modes(connector, edid);
drm_edid_to_eld(connector, edid);
kfree(edid); kfree(edid);

View File

@ -9314,7 +9314,8 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,
u32 offset; u32 offset;
int ret; int ret;
ret = drm_plane_helper_check_state(&plane_state->base, ret = drm_atomic_helper_check_plane_state(&plane_state->base,
&crtc_state->base,
&plane_state->clip, &plane_state->clip,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
@ -12794,7 +12795,8 @@ intel_check_primary_plane(struct intel_plane *plane,
can_position = true; can_position = true;
} }
ret = drm_plane_helper_check_state(&state->base, ret = drm_atomic_helper_check_plane_state(&state->base,
&crtc_state->base,
&state->clip, &state->clip,
min_scale, max_scale, min_scale, max_scale,
can_position, true); can_position, true);

View File

@ -5868,7 +5868,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
if (drm_add_edid_modes(connector, edid)) { if (drm_add_edid_modes(connector, edid)) {
drm_mode_connector_update_edid_property(connector, drm_mode_connector_update_edid_property(connector,
edid); edid);
drm_edid_to_eld(connector, edid);
} else { } else {
kfree(edid); kfree(edid);
edid = ERR_PTR(-EINVAL); edid = ERR_PTR(-EINVAL);

View File

@ -513,12 +513,14 @@ static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder,
static void static void
intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder, intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder,
const struct intel_crtc_state *crtc_state) const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{ {
union hdmi_infoframe frame; union hdmi_infoframe frame;
int ret; int ret;
ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi, ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
conn_state->connector,
&crtc_state->base.adjusted_mode); &crtc_state->base.adjusted_mode);
if (ret < 0) if (ret < 0)
return; return;
@ -585,7 +587,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
intel_hdmi_set_avi_infoframe(encoder, crtc_state); intel_hdmi_set_avi_infoframe(encoder, crtc_state);
intel_hdmi_set_spd_infoframe(encoder, crtc_state); intel_hdmi_set_spd_infoframe(encoder, crtc_state);
intel_hdmi_set_hdmi_infoframe(encoder, crtc_state); intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
} }
static bool hdmi_sink_is_deep_color(const struct drm_connector_state *conn_state) static bool hdmi_sink_is_deep_color(const struct drm_connector_state *conn_state)
@ -726,7 +728,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
intel_hdmi_set_avi_infoframe(encoder, crtc_state); intel_hdmi_set_avi_infoframe(encoder, crtc_state);
intel_hdmi_set_spd_infoframe(encoder, crtc_state); intel_hdmi_set_spd_infoframe(encoder, crtc_state);
intel_hdmi_set_hdmi_infoframe(encoder, crtc_state); intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
} }
static void cpt_set_infoframes(struct drm_encoder *encoder, static void cpt_set_infoframes(struct drm_encoder *encoder,
@ -769,7 +771,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder,
intel_hdmi_set_avi_infoframe(encoder, crtc_state); intel_hdmi_set_avi_infoframe(encoder, crtc_state);
intel_hdmi_set_spd_infoframe(encoder, crtc_state); intel_hdmi_set_spd_infoframe(encoder, crtc_state);
intel_hdmi_set_hdmi_infoframe(encoder, crtc_state); intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
} }
static void vlv_set_infoframes(struct drm_encoder *encoder, static void vlv_set_infoframes(struct drm_encoder *encoder,
@ -822,7 +824,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder,
intel_hdmi_set_avi_infoframe(encoder, crtc_state); intel_hdmi_set_avi_infoframe(encoder, crtc_state);
intel_hdmi_set_spd_infoframe(encoder, crtc_state); intel_hdmi_set_spd_infoframe(encoder, crtc_state);
intel_hdmi_set_hdmi_infoframe(encoder, crtc_state); intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
} }
static void hsw_set_infoframes(struct drm_encoder *encoder, static void hsw_set_infoframes(struct drm_encoder *encoder,
@ -855,7 +857,7 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
intel_hdmi_set_avi_infoframe(encoder, crtc_state); intel_hdmi_set_avi_infoframe(encoder, crtc_state);
intel_hdmi_set_spd_infoframe(encoder, crtc_state); intel_hdmi_set_spd_infoframe(encoder, crtc_state);
intel_hdmi_set_hdmi_infoframe(encoder, crtc_state); intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
} }
void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable) void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable)

View File

@ -57,7 +57,6 @@ int intel_connector_update_modes(struct drm_connector *connector,
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid); ret = drm_add_edid_modes(connector, edid);
drm_edid_to_eld(connector, edid);
intel_connector_update_eld_conn_type(connector); intel_connector_update_eld_conn_type(connector);

View File

@ -342,7 +342,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
clip.y1 = 0; clip.y1 = 0;
clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.x2 = crtc_state->adjusted_mode.hdisplay;
clip.y2 = crtc_state->adjusted_mode.vdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay;
ret = drm_plane_helper_check_state(state, &clip, ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
can_position, true); can_position, true);

View File

@ -111,7 +111,7 @@ static int mtk_plane_atomic_check(struct drm_plane *plane,
clip.x2 = crtc_state->mode.hdisplay; clip.x2 = crtc_state->mode.hdisplay;
clip.y2 = crtc_state->mode.vdisplay; clip.y2 = crtc_state->mode.vdisplay;
return drm_plane_helper_check_state(state, &clip, return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
true, true); true, true);

View File

@ -1054,7 +1054,8 @@ static int mtk_hdmi_setup_vendor_specific_infoframe(struct mtk_hdmi *hdmi,
u8 buffer[10]; u8 buffer[10];
ssize_t err; ssize_t err;
err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, mode); err = drm_hdmi_vendor_infoframe_from_display_mode(&frame,
&hdmi->conn, mode);
if (err) { if (err) {
dev_err(hdmi->dev, dev_err(hdmi->dev,
"Failed to get vendor infoframe from mode: %zd\n", err); "Failed to get vendor infoframe from mode: %zd\n", err);
@ -1222,7 +1223,6 @@ static int mtk_hdmi_conn_get_modes(struct drm_connector *conn)
drm_mode_connector_update_edid_property(conn, edid); drm_mode_connector_update_edid_property(conn, edid);
ret = drm_add_edid_modes(conn, edid); ret = drm_add_edid_modes(conn, edid);
drm_edid_to_eld(conn, edid);
kfree(edid); kfree(edid);
return ret; return ret;
} }

View File

@ -61,7 +61,7 @@ static int meson_plane_atomic_check(struct drm_plane *plane,
clip.x2 = crtc_state->mode.hdisplay; clip.x2 = crtc_state->mode.hdisplay;
clip.y2 = crtc_state->mode.vdisplay; clip.y2 = crtc_state->mode.vdisplay;
return drm_plane_helper_check_state(state, &clip, return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
true, true); true, true);

View File

@ -327,8 +327,9 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,
min_scale = FRAC_16_16(1, 8); min_scale = FRAC_16_16(1, 8);
max_scale = FRAC_16_16(8, 1); max_scale = FRAC_16_16(8, 1);
ret = drm_plane_helper_check_state(state, &clip, min_scale, ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
max_scale, true, true); min_scale, max_scale,
true, true);
if (ret) if (ret)
return ret; return ret;
@ -505,8 +506,9 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane,
min_scale = FRAC_16_16(1, 8); min_scale = FRAC_16_16(1, 8);
max_scale = FRAC_16_16(8, 1); max_scale = FRAC_16_16(8, 1);
ret = drm_plane_helper_check_state(state, &clip, min_scale, ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
max_scale, true, true); min_scale, max_scale,
true, true);
if (ret) if (ret)
return ret; return ret;

View File

@ -1143,7 +1143,8 @@ nv50_curs_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
{ {
int ret; int ret;
ret = drm_plane_helper_check_state(&asyw->state, &asyw->clip, ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
&asyw->clip,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
true, true); true, true);
@ -1432,7 +1433,8 @@ nv50_base_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
if (!fb->format->depth) if (!fb->format->depth)
return -EINVAL; return -EINVAL;
ret = drm_plane_helper_check_state(&asyw->state, &asyw->clip, ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
&asyw->clip,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
false, true); false, true);
@ -2688,7 +2690,6 @@ nv50_audio_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
if (!drm_detect_monitor_audio(nv_connector->edid)) if (!drm_detect_monitor_audio(nv_connector->edid))
return; return;
drm_edid_to_eld(&nv_connector->base, nv_connector->edid);
memcpy(args.data, nv_connector->base.eld, sizeof(args.data)); memcpy(args.data, nv_connector->base.eld, sizeof(args.data));
nvif_mthd(disp->disp, 0, &args, nvif_mthd(disp->disp, 0, &args,
@ -2755,7 +2756,8 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
= hdmi_infoframe_pack(&avi_frame, args.infoframes, 17); = hdmi_infoframe_pack(&avi_frame, args.infoframes, 17);
} }
ret = drm_hdmi_vendor_infoframe_from_display_mode(&vendor_frame.vendor.hdmi, mode); ret = drm_hdmi_vendor_infoframe_from_display_mode(&vendor_frame.vendor.hdmi,
&nv_connector->base, mode);
if (!ret) { if (!ret) {
/* We have a Vendor InfoFrame, populate it to the display */ /* We have a Vendor InfoFrame, populate it to the display */
args.pwr.vendor_infoframe_length args.pwr.vendor_infoframe_length
@ -3064,10 +3066,8 @@ nv50_mstc_get_modes(struct drm_connector *connector)
mstc->edid = drm_dp_mst_get_edid(&mstc->connector, mstc->port->mgr, mstc->port); mstc->edid = drm_dp_mst_get_edid(&mstc->connector, mstc->port->mgr, mstc->port);
drm_mode_connector_update_edid_property(&mstc->connector, mstc->edid); drm_mode_connector_update_edid_property(&mstc->connector, mstc->edid);
if (mstc->edid) { if (mstc->edid)
ret = drm_add_edid_modes(&mstc->connector, mstc->edid); ret = drm_add_edid_modes(&mstc->connector, mstc->edid);
drm_edid_to_eld(&mstc->connector, mstc->edid);
}
if (!mstc->connector.display_info.bpc) if (!mstc->connector.display_info.bpc)
mstc->connector.display_info.bpc = 8; mstc->connector.display_info.bpc = 8;

View File

@ -221,7 +221,7 @@ static struct rpi_touchscreen *panel_to_ts(struct drm_panel *panel)
return container_of(panel, struct rpi_touchscreen, base); return container_of(panel, struct rpi_touchscreen, base);
} }
static u8 rpi_touchscreen_i2c_read(struct rpi_touchscreen *ts, u8 reg) static int rpi_touchscreen_i2c_read(struct rpi_touchscreen *ts, u8 reg)
{ {
return i2c_smbus_read_byte_data(ts->i2c, reg); return i2c_smbus_read_byte_data(ts->i2c, reg);
} }

View File

@ -1356,6 +1356,38 @@ static const struct panel_desc lg_lp129qe = {
}, },
}; };
static const struct drm_display_mode mitsubishi_aa070mc01_mode = {
.clock = 30400,
.hdisplay = 800,
.hsync_start = 800 + 0,
.hsync_end = 800 + 1,
.htotal = 800 + 0 + 1 + 160,
.vdisplay = 480,
.vsync_start = 480 + 0,
.vsync_end = 480 + 48 + 1,
.vtotal = 480 + 48 + 1 + 0,
.vrefresh = 60,
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
};
static const struct panel_desc mitsubishi_aa070mc01 = {
.modes = &mitsubishi_aa070mc01_mode,
.num_modes = 1,
.bpc = 8,
.size = {
.width = 152,
.height = 91,
},
.delay = {
.enable = 200,
.unprepare = 200,
.disable = 400,
},
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
.bus_flags = DRM_BUS_FLAG_DE_HIGH,
};
static const struct display_timing nec_nl12880bc20_05_timing = { static const struct display_timing nec_nl12880bc20_05_timing = {
.pixelclock = { 67000000, 71000000, 75000000 }, .pixelclock = { 67000000, 71000000, 75000000 },
.hactive = { 1280, 1280, 1280 }, .hactive = { 1280, 1280, 1280 },
@ -1837,6 +1869,30 @@ static const struct panel_desc tianma_tm070jdhg30 = {
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
}; };
static const struct display_timing tianma_tm070rvhg71_timing = {
.pixelclock = { 27700000, 29200000, 39600000 },
.hactive = { 800, 800, 800 },
.hfront_porch = { 12, 40, 212 },
.hback_porch = { 88, 88, 88 },
.hsync_len = { 1, 1, 40 },
.vactive = { 480, 480, 480 },
.vfront_porch = { 1, 13, 88 },
.vback_porch = { 32, 32, 32 },
.vsync_len = { 1, 1, 3 },
.flags = DISPLAY_FLAGS_DE_HIGH,
};
static const struct panel_desc tianma_tm070rvhg71 = {
.timings = &tianma_tm070rvhg71_timing,
.num_timings = 1,
.bpc = 8,
.size = {
.width = 154,
.height = 86,
},
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
};
static const struct drm_display_mode toshiba_lt089ac29000_mode = { static const struct drm_display_mode toshiba_lt089ac29000_mode = {
.clock = 79500, .clock = 79500,
.hdisplay = 1280, .hdisplay = 1280,
@ -2085,6 +2141,9 @@ static const struct of_device_id platform_of_match[] = {
}, { }, {
.compatible = "lg,lp129qe", .compatible = "lg,lp129qe",
.data = &lg_lp129qe, .data = &lg_lp129qe,
}, {
.compatible = "mitsubishi,aa070mc01-ca1",
.data = &mitsubishi_aa070mc01,
}, { }, {
.compatible = "nec,nl12880bc20-05", .compatible = "nec,nl12880bc20-05",
.data = &nec_nl12880bc20_05, .data = &nec_nl12880bc20_05,
@ -2142,6 +2201,9 @@ static const struct of_device_id platform_of_match[] = {
}, { }, {
.compatible = "tianma,tm070jdhg30", .compatible = "tianma,tm070jdhg30",
.data = &tianma_tm070jdhg30, .data = &tianma_tm070jdhg30,
}, {
.compatible = "tianma,tm070rvhg71",
.data = &tianma_tm070rvhg71,
}, { }, {
.compatible = "toshiba,lt089ac29000", .compatible = "toshiba,lt089ac29000",
.data = &toshiba_lt089ac29000, .data = &toshiba_lt089ac29000,

View File

@ -123,11 +123,8 @@ int qxl_mmap(struct file *filp, struct vm_area_struct *vma)
struct qxl_device *qdev; struct qxl_device *qdev;
int r; int r;
if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) { if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
pr_info("%s: vma->vm_pgoff (%ld) < DRM_FILE_PAGE_OFFSET\n",
__func__, vma->vm_pgoff);
return -EINVAL; return -EINVAL;
}
file_priv = filp->private_data; file_priv = filp->private_data;
qdev = file_priv->minor->dev->dev_private; qdev = file_priv->minor->dev->dev_private;

View File

@ -392,7 +392,6 @@ static int radeon_ddc_get_modes(struct drm_connector *connector)
if (radeon_connector->edid) { if (radeon_connector->edid) {
drm_mode_connector_update_edid_property(connector, radeon_connector->edid); drm_mode_connector_update_edid_property(connector, radeon_connector->edid);
ret = drm_add_edid_modes(connector, radeon_connector->edid); ret = drm_add_edid_modes(connector, radeon_connector->edid);
drm_edid_to_eld(connector, radeon_connector->edid);
return ret; return ret;
} }
drm_mode_connector_update_edid_property(connector, NULL); drm_mode_connector_update_edid_property(connector, NULL);

View File

@ -197,7 +197,6 @@ static int radeon_dp_mst_get_ddc_modes(struct drm_connector *connector)
if (radeon_connector->edid) { if (radeon_connector->edid) {
drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid); drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid); ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
drm_edid_to_eld(&radeon_connector->base, radeon_connector->edid);
return ret; return ret;
} }
drm_mode_connector_update_edid_property(&radeon_connector->base, NULL); drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);

View File

@ -267,11 +267,10 @@ static struct drm_encoder_funcs rockchip_dp_encoder_funcs = {
.destroy = rockchip_dp_drm_encoder_destroy, .destroy = rockchip_dp_drm_encoder_destroy,
}; };
static int rockchip_dp_init(struct rockchip_dp_device *dp) static int rockchip_dp_of_probe(struct rockchip_dp_device *dp)
{ {
struct device *dev = dp->dev; struct device *dev = dp->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
int ret;
dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
if (IS_ERR(dp->grf)) { if (IS_ERR(dp->grf)) {
@ -301,19 +300,6 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp)
return PTR_ERR(dp->rst); return PTR_ERR(dp->rst);
} }
ret = clk_prepare_enable(dp->pclk);
if (ret < 0) {
DRM_DEV_ERROR(dp->dev, "failed to enable pclk %d\n", ret);
return ret;
}
ret = rockchip_dp_pre_init(dp);
if (ret < 0) {
DRM_DEV_ERROR(dp->dev, "failed to pre init %d\n", ret);
clk_disable_unprepare(dp->pclk);
return ret;
}
return 0; return 0;
} }
@ -359,10 +345,6 @@ static int rockchip_dp_bind(struct device *dev, struct device *master,
if (!dp_data) if (!dp_data)
return -ENODEV; return -ENODEV;
ret = rockchip_dp_init(dp);
if (ret < 0)
return ret;
dp->data = dp_data; dp->data = dp_data;
dp->drm_dev = drm_dev; dp->drm_dev = drm_dev;
@ -396,7 +378,6 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master,
rockchip_drm_psr_unregister(&dp->encoder); rockchip_drm_psr_unregister(&dp->encoder);
analogix_dp_unbind(dev, master, data); analogix_dp_unbind(dev, master, data);
clk_disable_unprepare(dp->pclk);
} }
static const struct component_ops rockchip_dp_component_ops = { static const struct component_ops rockchip_dp_component_ops = {
@ -412,7 +393,7 @@ static int rockchip_dp_probe(struct platform_device *pdev)
int ret; int ret;
ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL);
if (ret) if (ret < 0)
return ret; return ret;
dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
@ -420,9 +401,12 @@ static int rockchip_dp_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
dp->dev = dev; dp->dev = dev;
dp->plat_data.panel = panel; dp->plat_data.panel = panel;
ret = rockchip_dp_of_probe(dp);
if (ret < 0)
return ret;
/* /*
* We just use the drvdata until driver run into component * We just use the drvdata until driver run into component
* add function, and then we would set drvdata to null, so * add function, and then we would set drvdata to null, so

View File

@ -276,11 +276,9 @@ static int cdn_dp_connector_get_modes(struct drm_connector *connector)
dp->sink_has_audio = drm_detect_monitor_audio(edid); dp->sink_has_audio = drm_detect_monitor_audio(edid);
ret = drm_add_edid_modes(connector, edid); ret = drm_add_edid_modes(connector, edid);
if (ret) { if (ret)
drm_mode_connector_update_edid_property(connector, drm_mode_connector_update_edid_property(connector,
edid); edid);
drm_edid_to_eld(connector, edid);
}
} }
mutex_unlock(&dp->lock); mutex_unlock(&dp->lock);

View File

@ -282,6 +282,7 @@ static int inno_hdmi_config_video_vsi(struct inno_hdmi *hdmi,
int rc; int rc;
rc = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi, rc = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
&hdmi->connector,
mode); mode);
return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_VSI, return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_VSI,

View File

@ -659,7 +659,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.x2 = crtc_state->adjusted_mode.hdisplay;
clip.y2 = crtc_state->adjusted_mode.vdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay;
ret = drm_plane_helper_check_state(state, &clip, ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
min_scale, max_scale, min_scale, max_scale,
true, true); true, true);
if (ret) if (ret)

View File

@ -149,6 +149,34 @@ static const struct vop_data rk3036_vop = {
.win_size = ARRAY_SIZE(rk3036_vop_win_data), .win_size = ARRAY_SIZE(rk3036_vop_win_data),
}; };
static const struct vop_win_phy rk3126_win1_data = {
.data_formats = formats_win_lite,
.nformats = ARRAY_SIZE(formats_win_lite),
.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
.dsp_info = VOP_REG(RK3126_WIN1_DSP_INFO, 0x0fff0fff, 0),
.dsp_st = VOP_REG(RK3126_WIN1_DSP_ST, 0x1fff1fff, 0),
.yrgb_mst = VOP_REG(RK3126_WIN1_MST, 0xffffffff, 0),
.yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
};
static const struct vop_win_data rk3126_vop_win_data[] = {
{ .base = 0x00, .phy = &rk3036_win0_data,
.type = DRM_PLANE_TYPE_PRIMARY },
{ .base = 0x00, .phy = &rk3126_win1_data,
.type = DRM_PLANE_TYPE_CURSOR },
};
static const struct vop_data rk3126_vop = {
.intr = &rk3036_intr,
.common = &rk3036_common,
.modeset = &rk3036_modeset,
.output = &rk3036_output,
.win = rk3126_vop_win_data,
.win_size = ARRAY_SIZE(rk3126_vop_win_data),
};
static const struct vop_scl_extension rk3288_win_full_scl_ext = { static const struct vop_scl_extension rk3288_win_full_scl_ext = {
.cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31), .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
.cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30), .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
@ -510,6 +538,8 @@ static const struct vop_data rk3328_vop = {
static const struct of_device_id vop_driver_dt_match[] = { static const struct of_device_id vop_driver_dt_match[] = {
{ .compatible = "rockchip,rk3036-vop", { .compatible = "rockchip,rk3036-vop",
.data = &rk3036_vop }, .data = &rk3036_vop },
{ .compatible = "rockchip,rk3126-vop",
.data = &rk3126_vop },
{ .compatible = "rockchip,rk3288-vop", { .compatible = "rockchip,rk3288-vop",
.data = &rk3288_vop }, .data = &rk3288_vop },
{ .compatible = "rockchip,rk3368-vop", { .compatible = "rockchip,rk3368-vop",

View File

@ -878,4 +878,10 @@
#define RK3036_HWC_LUT_ADDR 0x800 #define RK3036_HWC_LUT_ADDR 0x800
/* rk3036 register definition end */ /* rk3036 register definition end */
/* rk3126 register definition */
#define RK3126_WIN1_MST 0x4c
#define RK3126_WIN1_DSP_INFO 0x50
#define RK3126_WIN1_DSP_ST 0x54
/* rk3126 register definition end */
#endif /* _ROCKCHIP_VOP_REG_H */ #endif /* _ROCKCHIP_VOP_REG_H */

View File

@ -682,6 +682,8 @@ static int __igt_insert(unsigned int count, u64 size, bool replace)
drm_mm_for_each_node_safe(node, next, &mm) drm_mm_for_each_node_safe(node, next, &mm)
drm_mm_remove_node(node); drm_mm_remove_node(node);
DRM_MM_BUG_ON(!drm_mm_clean(&mm)); DRM_MM_BUG_ON(!drm_mm_clean(&mm));
cond_resched();
} }
ret = 0; ret = 0;
@ -944,6 +946,8 @@ static int __igt_insert_range(unsigned int count, u64 size, u64 start, u64 end)
drm_mm_for_each_node_safe(node, next, &mm) drm_mm_for_each_node_safe(node, next, &mm)
drm_mm_remove_node(node); drm_mm_remove_node(node);
DRM_MM_BUG_ON(!drm_mm_clean(&mm)); DRM_MM_BUG_ON(!drm_mm_clean(&mm));
cond_resched();
} }
ret = 0; ret = 0;
@ -1068,6 +1072,7 @@ static int igt_align(void *ignored)
drm_mm_for_each_node_safe(node, next, &mm) drm_mm_for_each_node_safe(node, next, &mm)
drm_mm_remove_node(node); drm_mm_remove_node(node);
DRM_MM_BUG_ON(!drm_mm_clean(&mm)); DRM_MM_BUG_ON(!drm_mm_clean(&mm));
cond_resched(); cond_resched();
} }

View File

@ -8,5 +8,6 @@ config DRM_STI
select DRM_PANEL select DRM_PANEL
select FW_LOADER select FW_LOADER
select SND_SOC_HDMI_CODEC if SND_SOC select SND_SOC_HDMI_CODEC if SND_SOC
select OF
help help
Choose this option to enable DRM on STM stiH4xx chipset Choose this option to enable DRM on STM stiH4xx chipset

View File

@ -515,7 +515,9 @@ static int hdmi_vendor_infoframe_config(struct sti_hdmi *hdmi)
DRM_DEBUG_DRIVER("\n"); DRM_DEBUG_DRIVER("\n");
ret = drm_hdmi_vendor_infoframe_from_display_mode(&infoframe, mode); ret = drm_hdmi_vendor_infoframe_from_display_mode(&infoframe,
hdmi->drm_connector,
mode);
if (ret < 0) { if (ret < 0) {
/* /*
* Going into that statement does not means vendor infoframe * Going into that statement does not means vendor infoframe
@ -976,7 +978,6 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
count = drm_add_edid_modes(connector, edid); count = drm_add_edid_modes(connector, edid);
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
drm_edid_to_eld(connector, edid);
kfree(edid); kfree(edid);
return count; return count;
@ -1414,6 +1415,11 @@ static int sti_hdmi_probe(struct platform_device *pdev)
init_waitqueue_head(&hdmi->wait_event); init_waitqueue_head(&hdmi->wait_event);
hdmi->irq = platform_get_irq_byname(pdev, "irq"); hdmi->irq = platform_get_irq_byname(pdev, "irq");
if (hdmi->irq < 0) {
DRM_ERROR("Cannot get HDMI irq\n");
ret = hdmi->irq;
goto release_adapter;
}
ret = devm_request_threaded_irq(dev, hdmi->irq, hdmi_irq, ret = devm_request_threaded_irq(dev, hdmi->irq, hdmi_irq,
hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi); hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi);

View File

@ -9,6 +9,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <drm/drmP.h> #include <drm/drmP.h>
@ -72,8 +73,6 @@
#define AWG_DELAY_ED (-8) #define AWG_DELAY_ED (-8)
#define AWG_DELAY_SD (-7) #define AWG_DELAY_SD (-7)
static LIST_HEAD(vtg_lookup);
/* /*
* STI VTG register offset structure * STI VTG register offset structure
* *
@ -123,42 +122,31 @@ struct sti_vtg_sync_params {
/** /**
* STI VTG structure * STI VTG structure
* *
* @dev: pointer to device driver
* @np: device node
* @regs: register mapping * @regs: register mapping
* @sync_params: synchronisation parameters used to generate timings * @sync_params: synchronisation parameters used to generate timings
* @irq: VTG irq * @irq: VTG irq
* @irq_status: store the IRQ status value * @irq_status: store the IRQ status value
* @notifier_list: notifier callback * @notifier_list: notifier callback
* @crtc: the CRTC for vblank event * @crtc: the CRTC for vblank event
* @link: List node to link the structure in lookup list
*/ */
struct sti_vtg { struct sti_vtg {
struct device *dev;
struct device_node *np;
void __iomem *regs; void __iomem *regs;
struct sti_vtg_sync_params sync_params[VTG_MAX_SYNC_OUTPUT]; struct sti_vtg_sync_params sync_params[VTG_MAX_SYNC_OUTPUT];
int irq; int irq;
u32 irq_status; u32 irq_status;
struct raw_notifier_head notifier_list; struct raw_notifier_head notifier_list;
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct list_head link;
}; };
static void vtg_register(struct sti_vtg *vtg)
{
list_add_tail(&vtg->link, &vtg_lookup);
}
struct sti_vtg *of_vtg_find(struct device_node *np) struct sti_vtg *of_vtg_find(struct device_node *np)
{ {
struct sti_vtg *vtg; struct platform_device *pdev;
list_for_each_entry(vtg, &vtg_lookup, link) { pdev = of_find_device_by_node(np);
if (vtg->np == np) if (!pdev)
return vtg;
}
return NULL; return NULL;
return (struct sti_vtg *)platform_get_drvdata(pdev);
} }
static void vtg_reset(struct sti_vtg *vtg) static void vtg_reset(struct sti_vtg *vtg)
@ -397,9 +385,6 @@ static int vtg_probe(struct platform_device *pdev)
if (!vtg) if (!vtg)
return -ENOMEM; return -ENOMEM;
vtg->dev = dev;
vtg->np = pdev->dev.of_node;
/* Get Memory ressources */ /* Get Memory ressources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
@ -428,19 +413,13 @@ static int vtg_probe(struct platform_device *pdev)
return ret; return ret;
} }
vtg_register(vtg);
platform_set_drvdata(pdev, vtg); platform_set_drvdata(pdev, vtg);
DRM_INFO("%s %s\n", __func__, dev_name(vtg->dev)); DRM_INFO("%s %s\n", __func__, dev_name(dev));
return 0; return 0;
} }
static int vtg_remove(struct platform_device *pdev)
{
return 0;
}
static const struct of_device_id vtg_of_match[] = { static const struct of_device_id vtg_of_match[] = {
{ .compatible = "st,vtg", }, { .compatible = "st,vtg", },
{ /* sentinel */ } { /* sentinel */ }
@ -454,7 +433,6 @@ struct platform_driver sti_vtg_driver = {
.of_match_table = vtg_of_match, .of_match_table = vtg_of_match,
}, },
.probe = vtg_probe, .probe = vtg_probe,
.remove = vtg_remove,
}; };
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");

View File

@ -129,7 +129,7 @@ static int dsi_pll_get_params(int clkin_khz, int clkout_khz,
int fvco_min, fvco_max, delta, best_delta; /* all in khz */ int fvco_min, fvco_max, delta, best_delta; /* all in khz */
/* Early checks preventing division by 0 & odd results */ /* Early checks preventing division by 0 & odd results */
if ((clkin_khz <= 0) || (clkout_khz <= 0)) if (clkin_khz <= 0 || clkout_khz <= 0)
return -EINVAL; return -EINVAL;
fvco_min = LANE_MIN_KBPS * 2 * ODF_MAX; fvco_min = LANE_MIN_KBPS * 2 * ODF_MAX;
@ -155,7 +155,7 @@ static int dsi_pll_get_params(int clkin_khz, int clkout_khz,
for (o = ODF_MIN; o <= ODF_MAX; o *= 2) { for (o = ODF_MIN; o <= ODF_MAX; o *= 2) {
n = DIV_ROUND_CLOSEST(i * o * clkout_khz, clkin_khz); n = DIV_ROUND_CLOSEST(i * o * clkout_khz, clkin_khz);
/* Check ndiv according to vco range */ /* Check ndiv according to vco range */
if ((n < n_min) || (n > n_max)) if (n < n_min || n > n_max)
continue; continue;
/* Check if new delta is better & saves parameters */ /* Check if new delta is better & saves parameters */
delta = dsi_pll_get_clkout_khz(clkin_khz, i, n, o) - delta = dsi_pll_get_clkout_khz(clkin_khz, i, n, o) -
@ -342,7 +342,7 @@ static struct platform_driver dw_mipi_dsi_stm_driver = {
.remove = dw_mipi_dsi_stm_remove, .remove = dw_mipi_dsi_stm_remove,
.driver = { .driver = {
.of_match_table = dw_mipi_dsi_stm_dt_ids, .of_match_table = dw_mipi_dsi_stm_dt_ids,
.name = "dw_mipi_dsi-stm", .name = "stm32-display-dsi",
}, },
}; };

View File

@ -33,6 +33,8 @@
#define MAX_IRQ 4 #define MAX_IRQ 4
#define MAX_ENDPOINTS 2
#define HWVER_10200 0x010200 #define HWVER_10200 0x010200
#define HWVER_10300 0x010300 #define HWVER_10300 0x010300
#define HWVER_20101 0x020101 #define HWVER_20101 0x020101
@ -556,7 +558,7 @@ static int ltdc_plane_atomic_check(struct drm_plane *plane,
src_h = state->src_h >> 16; src_h = state->src_h >> 16;
/* Reject scaling */ /* Reject scaling */
if ((src_w != state->crtc_w) || (src_h != state->crtc_h)) { if (src_w != state->crtc_w || src_h != state->crtc_h) {
DRM_ERROR("Scaling is not supported"); DRM_ERROR("Scaling is not supported");
return -EINVAL; return -EINVAL;
} }
@ -856,18 +858,33 @@ int ltdc_load(struct drm_device *ddev)
struct ltdc_device *ldev = ddev->dev_private; struct ltdc_device *ldev = ddev->dev_private;
struct device *dev = ddev->dev; struct device *dev = ddev->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct drm_bridge *bridge; struct drm_bridge *bridge[MAX_ENDPOINTS] = {NULL};
struct drm_panel *panel; struct drm_panel *panel[MAX_ENDPOINTS] = {NULL};
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct reset_control *rstc; struct reset_control *rstc;
struct resource *res; struct resource *res;
int irq, ret, i; int irq, ret, i, endpoint_not_ready = -ENODEV;
DRM_DEBUG_DRIVER("\n"); DRM_DEBUG_DRIVER("\n");
ret = drm_of_find_panel_or_bridge(np, 0, 0, &panel, &bridge); /* Get endpoints if any */
if (ret) for (i = 0; i < MAX_ENDPOINTS; i++) {
return ret; ret = drm_of_find_panel_or_bridge(np, 0, i, &panel[i],
&bridge[i]);
/*
* If at least one endpoint is ready, continue probing,
* else if at least one endpoint is -EPROBE_DEFER and
* there is no previous ready endpoints, defer probing.
*/
if (!ret)
endpoint_not_ready = 0;
else if (ret == -EPROBE_DEFER && endpoint_not_ready)
endpoint_not_ready = -EPROBE_DEFER;
}
if (endpoint_not_ready)
return endpoint_not_ready;
rstc = devm_reset_control_get_exclusive(dev, NULL); rstc = devm_reset_control_get_exclusive(dev, NULL);
@ -928,20 +945,26 @@ int ltdc_load(struct drm_device *ddev)
DRM_INFO("ltdc hw version 0x%08x - ready\n", ldev->caps.hw_version); DRM_INFO("ltdc hw version 0x%08x - ready\n", ldev->caps.hw_version);
if (panel) { /* Add endpoints panels or bridges if any */
bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DPI); for (i = 0; i < MAX_ENDPOINTS; i++) {
if (IS_ERR(bridge)) { if (panel[i]) {
DRM_ERROR("Failed to create panel-bridge\n"); bridge[i] = drm_panel_bridge_add(panel[i],
ret = PTR_ERR(bridge); DRM_MODE_CONNECTOR_DPI);
if (IS_ERR(bridge[i])) {
DRM_ERROR("panel-bridge endpoint %d\n", i);
ret = PTR_ERR(bridge[i]);
goto err; goto err;
} }
} }
ret = ltdc_encoder_init(ddev, bridge); if (bridge[i]) {
ret = ltdc_encoder_init(ddev, bridge[i]);
if (ret) { if (ret) {
DRM_ERROR("Failed to init encoder\n"); DRM_ERROR("init encoder endpoint %d\n", i);
goto err; goto err;
} }
}
}
crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL); crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL);
if (!crtc) { if (!crtc) {
@ -968,7 +991,8 @@ int ltdc_load(struct drm_device *ddev)
return 0; return 0;
err: err:
drm_panel_bridge_remove(bridge); for (i = 0; i < MAX_ENDPOINTS; i++)
drm_panel_bridge_remove(bridge[i]);
clk_disable_unprepare(ldev->pixel_clk); clk_disable_unprepare(ldev->pixel_clk);
@ -978,10 +1002,12 @@ err:
void ltdc_unload(struct drm_device *ddev) void ltdc_unload(struct drm_device *ddev)
{ {
struct ltdc_device *ldev = ddev->dev_private; struct ltdc_device *ldev = ddev->dev_private;
int i;
DRM_DEBUG_DRIVER("\n"); DRM_DEBUG_DRIVER("\n");
drm_of_panel_bridge_remove(ddev->dev->of_node, 0, 0); for (i = 0; i < MAX_ENDPOINTS; i++)
drm_of_panel_bridge_remove(ddev->dev->of_node, 0, i);
clk_disable_unprepare(ldev->pixel_clk); clk_disable_unprepare(ldev->pixel_clk);
} }

View File

@ -491,8 +491,8 @@ static int tegra_plane_state_add(struct tegra_plane *plane,
clip.y2 = crtc_state->mode.vdisplay; clip.y2 = crtc_state->mode.vdisplay;
/* Check plane state for visibility and calculate clipping bounds */ /* Check plane state for visibility and calculate clipping bounds */
err = drm_plane_helper_check_state(state, &clip, 0, INT_MAX, err = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
true, true); 0, INT_MAX, true, true);
if (err < 0) if (err < 0)
return err; return err;

View File

@ -39,7 +39,6 @@ int tegra_output_connector_get_modes(struct drm_connector *connector)
if (edid) { if (edid) {
err = drm_add_edid_modes(connector, edid); err = drm_add_edid_modes(connector, edid);
drm_edid_to_eld(connector, edid);
kfree(edid); kfree(edid);
} }

View File

@ -507,7 +507,6 @@ static int tilcdc_mm_show(struct seq_file *m, void *arg)
static struct drm_info_list tilcdc_debugfs_list[] = { static struct drm_info_list tilcdc_debugfs_list[] = {
{ "regs", tilcdc_regs_show, 0 }, { "regs", tilcdc_regs_show, 0 },
{ "mm", tilcdc_mm_show, 0 }, { "mm", tilcdc_mm_show, 0 },
{ "fb", drm_fb_cma_debugfs_show, 0 },
}; };
static int tilcdc_debugfs_init(struct drm_minor *minor) static int tilcdc_debugfs_init(struct drm_minor *minor)
@ -541,6 +540,7 @@ static struct drm_driver tilcdc_driver = {
.lastclose = tilcdc_lastclose, .lastclose = tilcdc_lastclose,
.irq_handler = tilcdc_irq, .irq_handler = tilcdc_irq,
.gem_free_object_unlocked = drm_gem_cma_free_object, .gem_free_object_unlocked = drm_gem_cma_free_object,
.gem_print_info = drm_gem_cma_print_info,
.gem_vm_ops = &drm_gem_cma_vm_ops, .gem_vm_ops = &drm_gem_cma_vm_ops,
.dumb_create = drm_gem_cma_dumb_create, .dumb_create = drm_gem_cma_dumb_create,

View File

@ -414,11 +414,9 @@ tinydrm_dbg_spi_print(struct spi_device *spi, struct spi_transfer *tr,
void _tinydrm_dbg_spi_message(struct spi_device *spi, struct spi_message *m) void _tinydrm_dbg_spi_message(struct spi_device *spi, struct spi_message *m)
{ {
struct spi_transfer *tmp; struct spi_transfer *tmp;
struct list_head *pos;
int i = 0; int i = 0;
list_for_each(pos, &m->transfers) { list_for_each_entry(tmp, &m->transfers, transfer_list) {
tmp = list_entry(pos, struct spi_transfer, transfer_list);
if (tmp->tx_buf) if (tmp->tx_buf)
tinydrm_dbg_spi_print(spi, tmp, tmp->tx_buf, i, true); tinydrm_dbg_spi_print(spi, tmp, tmp->tx_buf, i, true);

View File

@ -961,10 +961,6 @@ static const struct file_operations mipi_dbi_debugfs_command_fops = {
.write = mipi_dbi_debugfs_command_write, .write = mipi_dbi_debugfs_command_write,
}; };
static const struct drm_info_list mipi_dbi_debugfs_list[] = {
{ "fb", drm_fb_cma_debugfs_show, 0 },
};
/** /**
* mipi_dbi_debugfs_init - Create debugfs entries * mipi_dbi_debugfs_init - Create debugfs entries
* @minor: DRM minor * @minor: DRM minor
@ -987,9 +983,7 @@ int mipi_dbi_debugfs_init(struct drm_minor *minor)
debugfs_create_file("command", mode, minor->debugfs_root, mipi, debugfs_create_file("command", mode, minor->debugfs_root, mipi,
&mipi_dbi_debugfs_command_fops); &mipi_dbi_debugfs_command_fops);
return drm_debugfs_create_files(mipi_dbi_debugfs_list, return 0;
ARRAY_SIZE(mipi_dbi_debugfs_list),
minor->debugfs_root, minor);
} }
EXPORT_SYMBOL(mipi_dbi_debugfs_init); EXPORT_SYMBOL(mipi_dbi_debugfs_init);

View File

@ -287,7 +287,6 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid); ret = drm_add_edid_modes(connector, edid);
drm_edid_to_eld(connector, edid);
kfree(edid); kfree(edid);
return ret; return ret;
@ -695,7 +694,22 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
} }
} }
static enum drm_mode_status
vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc,
const struct drm_display_mode *mode)
{
/* HSM clock must be 108% of the pixel clock. Additionally,
* the AXI clock needs to be at least 25% of pixel clock, but
* HSM ends up being the limiting factor.
*/
if (mode->clock > HSM_CLOCK_FREQ / (1000 * 108 / 100))
return MODE_CLOCK_HIGH;
return MODE_OK;
}
static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
.mode_valid = vc4_hdmi_encoder_mode_valid,
.disable = vc4_hdmi_encoder_disable, .disable = vc4_hdmi_encoder_disable,
.enable = vc4_hdmi_encoder_enable, .enable = vc4_hdmi_encoder_enable,
}; };

View File

@ -86,7 +86,6 @@ static const struct hvs_format {
u32 hvs; /* HVS_FORMAT_* */ u32 hvs; /* HVS_FORMAT_* */
u32 pixel_order; u32 pixel_order;
bool has_alpha; bool has_alpha;
bool flip_cbcr;
} hvs_formats[] = { } hvs_formats[] = {
{ {
.drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, .drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
@ -120,31 +119,53 @@ static const struct hvs_format {
.drm = DRM_FORMAT_XRGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551, .drm = DRM_FORMAT_XRGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551,
.pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = false, .pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = false,
}, },
{
.drm = DRM_FORMAT_RGB888, .hvs = HVS_PIXEL_FORMAT_RGB888,
.pixel_order = HVS_PIXEL_ORDER_XRGB, .has_alpha = false,
},
{
.drm = DRM_FORMAT_BGR888, .hvs = HVS_PIXEL_FORMAT_RGB888,
.pixel_order = HVS_PIXEL_ORDER_XBGR, .has_alpha = false,
},
{ {
.drm = DRM_FORMAT_YUV422, .drm = DRM_FORMAT_YUV422,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
}, },
{ {
.drm = DRM_FORMAT_YVU422, .drm = DRM_FORMAT_YVU422,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
.flip_cbcr = true, .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
}, },
{ {
.drm = DRM_FORMAT_YUV420, .drm = DRM_FORMAT_YUV420,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
}, },
{ {
.drm = DRM_FORMAT_YVU420, .drm = DRM_FORMAT_YVU420,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
.flip_cbcr = true, .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
}, },
{ {
.drm = DRM_FORMAT_NV12, .drm = DRM_FORMAT_NV12,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
},
{
.drm = DRM_FORMAT_NV21,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCRCB,
}, },
{ {
.drm = DRM_FORMAT_NV16, .drm = DRM_FORMAT_NV16,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCBCR,
},
{
.drm = DRM_FORMAT_NV61,
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCRCB,
}, },
}; };
@ -617,15 +638,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
* The pointers may be any byte address. * The pointers may be any byte address.
*/ */
vc4_state->ptr0_offset = vc4_state->dlist_count; vc4_state->ptr0_offset = vc4_state->dlist_count;
if (!format->flip_cbcr) {
for (i = 0; i < num_planes; i++) for (i = 0; i < num_planes; i++)
vc4_dlist_write(vc4_state, vc4_state->offsets[i]); vc4_dlist_write(vc4_state, vc4_state->offsets[i]);
} else {
WARN_ON_ONCE(num_planes != 3);
vc4_dlist_write(vc4_state, vc4_state->offsets[0]);
vc4_dlist_write(vc4_state, vc4_state->offsets[2]);
vc4_dlist_write(vc4_state, vc4_state->offsets[1]);
}
/* Pointer Context Word 0/1/2: Written by the HVS */ /* Pointer Context Word 0/1/2: Written by the HVS */
for (i = 0; i < num_planes; i++) for (i = 0; i < num_planes; i++)

View File

@ -74,9 +74,9 @@ typedef struct drm_via_private {
volatile uint32_t *last_pause_ptr; volatile uint32_t *last_pause_ptr;
volatile uint32_t *hw_addr_ptr; volatile uint32_t *hw_addr_ptr;
drm_via_ring_buffer_t ring; drm_via_ring_buffer_t ring;
struct timeval last_vblank; ktime_t last_vblank;
int last_vblank_valid; int last_vblank_valid;
unsigned usec_per_vblank; ktime_t nsec_per_vblank;
atomic_t vbl_received; atomic_t vbl_received;
drm_via_state_t hc_state; drm_via_state_t hc_state;
char pci_buf[VIA_PCI_BUF_SIZE]; char pci_buf[VIA_PCI_BUF_SIZE];

View File

@ -88,13 +88,6 @@ static int via_num_unichrome = ARRAY_SIZE(via_unichrome_irqs);
static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1}; static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
static unsigned time_diff(struct timeval *now, struct timeval *then)
{
return (now->tv_usec >= then->tv_usec) ?
now->tv_usec - then->tv_usec :
1000000 - (then->tv_usec - now->tv_usec);
}
u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe) u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
{ {
drm_via_private_t *dev_priv = dev->dev_private; drm_via_private_t *dev_priv = dev->dev_private;
@ -111,7 +104,7 @@ irqreturn_t via_driver_irq_handler(int irq, void *arg)
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
u32 status; u32 status;
int handled = 0; int handled = 0;
struct timeval cur_vblank; ktime_t cur_vblank;
drm_via_irq_t *cur_irq = dev_priv->via_irqs; drm_via_irq_t *cur_irq = dev_priv->via_irqs;
int i; int i;
@ -119,18 +112,18 @@ irqreturn_t via_driver_irq_handler(int irq, void *arg)
if (status & VIA_IRQ_VBLANK_PENDING) { if (status & VIA_IRQ_VBLANK_PENDING) {
atomic_inc(&dev_priv->vbl_received); atomic_inc(&dev_priv->vbl_received);
if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) { if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
do_gettimeofday(&cur_vblank); cur_vblank = ktime_get();
if (dev_priv->last_vblank_valid) { if (dev_priv->last_vblank_valid) {
dev_priv->usec_per_vblank = dev_priv->nsec_per_vblank =
time_diff(&cur_vblank, ktime_sub(cur_vblank,
&dev_priv->last_vblank) >> 4; dev_priv->last_vblank) >> 4;
} }
dev_priv->last_vblank = cur_vblank; dev_priv->last_vblank = cur_vblank;
dev_priv->last_vblank_valid = 1; dev_priv->last_vblank_valid = 1;
} }
if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) { if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
DRM_DEBUG("US per vblank is: %u\n", DRM_DEBUG("nsec per vblank is: %llu\n",
dev_priv->usec_per_vblank); ktime_to_ns(dev_priv->nsec_per_vblank));
} }
drm_handle_vblank(dev, 0); drm_handle_vblank(dev, 0);
handled = 1; handled = 1;
@ -350,7 +343,7 @@ void via_driver_irq_uninstall(struct drm_device *dev)
int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv) int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
{ {
drm_via_irqwait_t *irqwait = data; drm_via_irqwait_t *irqwait = data;
struct timeval now; struct timespec64 now;
int ret = 0; int ret = 0;
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
drm_via_irq_t *cur_irq = dev_priv->via_irqs; drm_via_irq_t *cur_irq = dev_priv->via_irqs;
@ -384,9 +377,9 @@ int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence, ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence,
&irqwait->request.sequence); &irqwait->request.sequence);
do_gettimeofday(&now); ktime_get_ts64(&now);
irqwait->reply.tval_sec = now.tv_sec; irqwait->reply.tval_sec = now.tv_sec;
irqwait->reply.tval_usec = now.tv_usec; irqwait->reply.tval_usec = now.tv_nsec / NSEC_PER_USEC;
return ret; return ret;
} }

View File

@ -71,7 +71,19 @@ virtio_gpu_framebuffer_surface_dirty(struct drm_framebuffer *fb,
return virtio_gpu_surface_dirty(virtio_gpu_fb, clips, num_clips); return virtio_gpu_surface_dirty(virtio_gpu_fb, clips, num_clips);
} }
static int
virtio_gpu_framebuffer_create_handle(struct drm_framebuffer *fb,
struct drm_file *file_priv,
unsigned int *handle)
{
struct virtio_gpu_framebuffer *virtio_gpu_fb =
to_virtio_gpu_framebuffer(fb);
return drm_gem_handle_create(file_priv, virtio_gpu_fb->obj, handle);
}
static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs = { static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs = {
.create_handle = virtio_gpu_framebuffer_create_handle,
.destroy = virtio_gpu_user_framebuffer_destroy, .destroy = virtio_gpu_user_framebuffer_destroy,
.dirty = virtio_gpu_framebuffer_surface_dirty, .dirty = virtio_gpu_framebuffer_surface_dirty,
}; };

View File

@ -261,7 +261,7 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
ret = virtio_gpu_object_attach(vgdev, qobj, res_id, NULL); ret = virtio_gpu_object_attach(vgdev, qobj, res_id, NULL);
} else { } else {
/* use a gem reference since unref list undoes them */ /* use a gem reference since unref list undoes them */
drm_gem_object_reference(&qobj->gem_base); drm_gem_object_get(&qobj->gem_base);
mainbuf.bo = &qobj->tbo; mainbuf.bo = &qobj->tbo;
list_add(&mainbuf.head, &validate_list); list_add(&mainbuf.head, &validate_list);

View File

@ -272,20 +272,18 @@ int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file)
struct virtio_gpu_device *vgdev = dev->dev_private; struct virtio_gpu_device *vgdev = dev->dev_private;
struct virtio_gpu_fpriv *vfpriv; struct virtio_gpu_fpriv *vfpriv;
uint32_t id; uint32_t id;
char dbgname[64], tmpname[TASK_COMM_LEN]; char dbgname[TASK_COMM_LEN];
/* can't create contexts without 3d renderer */ /* can't create contexts without 3d renderer */
if (!vgdev->has_virgl_3d) if (!vgdev->has_virgl_3d)
return 0; return 0;
get_task_comm(tmpname, current);
snprintf(dbgname, sizeof(dbgname), "%s", tmpname);
dbgname[63] = 0;
/* allocate a virt GPU context for this opener */ /* allocate a virt GPU context for this opener */
vfpriv = kzalloc(sizeof(*vfpriv), GFP_KERNEL); vfpriv = kzalloc(sizeof(*vfpriv), GFP_KERNEL);
if (!vfpriv) if (!vfpriv)
return -ENOMEM; return -ENOMEM;
get_task_comm(dbgname, current);
virtio_gpu_context_create(vgdev, strlen(dbgname), dbgname, &id); virtio_gpu_context_create(vgdev, strlen(dbgname), dbgname, &id);
vfpriv->ctx_id = id; vfpriv->ctx_id = id;

View File

@ -441,31 +441,23 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
int vmw_du_primary_plane_atomic_check(struct drm_plane *plane, int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state) struct drm_plane_state *state)
{ {
struct drm_crtc_state *crtc_state = NULL;
struct drm_framebuffer *new_fb = state->fb; struct drm_framebuffer *new_fb = state->fb;
bool visible; struct drm_rect clip = {};
struct drm_rect src = {
.x1 = state->src_x,
.y1 = state->src_y,
.x2 = state->src_x + state->src_w,
.y2 = state->src_y + state->src_h,
};
struct drm_rect dest = {
.x1 = state->crtc_x,
.y1 = state->crtc_y,
.x2 = state->crtc_x + state->crtc_w,
.y2 = state->crtc_y + state->crtc_h,
};
struct drm_rect clip = dest;
int ret; int ret;
ret = drm_plane_helper_check_update(plane, state->crtc, new_fb, if (state->crtc)
&src, &dest, &clip, crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc);
DRM_MODE_ROTATE_0,
DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING,
false, true, &visible);
if (crtc_state && crtc_state->enable) {
clip.x2 = crtc_state->adjusted_mode.hdisplay;
clip.y2 = crtc_state->adjusted_mode.vdisplay;
}
ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING,
false, true);
if (!ret && new_fb) { if (!ret && new_fb) {
struct drm_crtc *crtc = state->crtc; struct drm_crtc *crtc = state->crtc;
@ -476,12 +468,6 @@ int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
vcs = vmw_connector_state_to_vcs(du->connector.state); vcs = vmw_connector_state_to_vcs(du->connector.state);
if ((dest.x2 > new_fb->width ||
dest.y2 > new_fb->height)) {
DRM_ERROR("CRTC area outside of framebuffer\n");
return -EINVAL;
}
/* Only one active implicit framebuffer at a time. */ /* Only one active implicit framebuffer at a time. */
mutex_lock(&dev_priv->global_kms_state_mutex); mutex_lock(&dev_priv->global_kms_state_mutex);
if (vcs->is_implicit && dev_priv->implicit_fb && if (vcs->is_implicit && dev_priv->implicit_fb &&

View File

@ -108,6 +108,7 @@ static int zx_hdmi_config_video_vsi(struct zx_hdmi *hdmi,
int ret; int ret;
ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi, ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
&hdmi->connector,
mode); mode);
if (ret) { if (ret) {
DRM_DEV_ERROR(hdmi->dev, "failed to get vendor infoframe: %d\n", DRM_DEV_ERROR(hdmi->dev, "failed to get vendor infoframe: %d\n",

View File

@ -80,8 +80,8 @@ static int zx_vl_plane_atomic_check(struct drm_plane *plane,
clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.x2 = crtc_state->adjusted_mode.hdisplay;
clip.y2 = crtc_state->adjusted_mode.vdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay;
return drm_plane_helper_check_state(plane_state, &clip, return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
min_scale, max_scale, &clip, min_scale, max_scale,
true, true); true, true);
} }
@ -315,7 +315,8 @@ static int zx_gl_plane_atomic_check(struct drm_plane *plane,
clip.x2 = crtc_state->adjusted_mode.hdisplay; clip.x2 = crtc_state->adjusted_mode.hdisplay;
clip.y2 = crtc_state->adjusted_mode.vdisplay; clip.y2 = crtc_state->adjusted_mode.vdisplay;
return drm_plane_helper_check_state(plane_state, &clip, return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
&clip,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
false, true); false, true);

View File

@ -321,6 +321,17 @@ int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame)
} }
EXPORT_SYMBOL(hdmi_vendor_infoframe_init); EXPORT_SYMBOL(hdmi_vendor_infoframe_init);
static int hdmi_vendor_infoframe_length(const struct hdmi_vendor_infoframe *frame)
{
/* for side by side (half) we also need to provide 3D_Ext_Data */
if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
return 6;
else if (frame->vic != 0 || frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID)
return 5;
else
return 4;
}
/** /**
* hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary buffer * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary buffer
* @frame: HDMI infoframe * @frame: HDMI infoframe
@ -341,19 +352,11 @@ ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
u8 *ptr = buffer; u8 *ptr = buffer;
size_t length; size_t length;
/* empty info frame */
if (frame->vic == 0 && frame->s3d_struct == HDMI_3D_STRUCTURE_INVALID)
return -EINVAL;
/* only one of those can be supplied */ /* only one of those can be supplied */
if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID) if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID)
return -EINVAL; return -EINVAL;
/* for side by side (half) we also need to provide 3D_Ext_Data */ frame->length = hdmi_vendor_infoframe_length(frame);
if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
frame->length = 6;
else
frame->length = 5;
length = HDMI_INFOFRAME_HEADER_SIZE + frame->length; length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
@ -372,14 +375,16 @@ ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
ptr[5] = 0x0c; ptr[5] = 0x0c;
ptr[6] = 0x00; ptr[6] = 0x00;
if (frame->vic) { if (frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID) {
ptr[7] = 0x1 << 5; /* video format */
ptr[8] = frame->vic;
} else {
ptr[7] = 0x2 << 5; /* video format */ ptr[7] = 0x2 << 5; /* video format */
ptr[8] = (frame->s3d_struct & 0xf) << 4; ptr[8] = (frame->s3d_struct & 0xf) << 4;
if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
ptr[9] = (frame->s3d_ext_data & 0xf) << 4; ptr[9] = (frame->s3d_ext_data & 0xf) << 4;
} else if (frame->vic) {
ptr[7] = 0x1 << 5; /* video format */
ptr[8] = frame->vic;
} else {
ptr[7] = 0x0 << 5; /* video format */
} }
hdmi_infoframe_set_checksum(buffer, length); hdmi_infoframe_set_checksum(buffer, length);
@ -1165,7 +1170,7 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR || if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR ||
ptr[1] != 1 || ptr[1] != 1 ||
(ptr[2] != 5 && ptr[2] != 6)) (ptr[2] != 4 && ptr[2] != 5 && ptr[2] != 6))
return -EINVAL; return -EINVAL;
length = ptr[2]; length = ptr[2];
@ -1193,16 +1198,22 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
hvf->length = length; hvf->length = length;
if (hdmi_video_format == 0x1) { if (hdmi_video_format == 0x2) {
hvf->vic = ptr[4]; if (length != 5 && length != 6)
} else if (hdmi_video_format == 0x2) { return -EINVAL;
hvf->s3d_struct = ptr[4] >> 4; hvf->s3d_struct = ptr[4] >> 4;
if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) { if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) {
if (length == 6) if (length != 6)
hvf->s3d_ext_data = ptr[5] >> 4;
else
return -EINVAL; return -EINVAL;
hvf->s3d_ext_data = ptr[5] >> 4;
} }
} else if (hdmi_video_format == 0x1) {
if (length != 5)
return -EINVAL;
hvf->vic = ptr[4];
} else {
if (length != 4)
return -EINVAL;
} }
return 0; return 0;

View File

@ -75,6 +75,7 @@
#include <drm/drm_sarea.h> #include <drm/drm_sarea.h>
#include <drm/drm_drv.h> #include <drm/drm_drv.h>
#include <drm/drm_prime.h> #include <drm/drm_prime.h>
#include <drm/drm_print.h>
#include <drm/drm_pci.h> #include <drm/drm_pci.h>
#include <drm/drm_file.h> #include <drm/drm_file.h>
#include <drm/drm_debugfs.h> #include <drm/drm_debugfs.h>
@ -94,212 +95,16 @@ struct dma_buf_attachment;
struct pci_dev; struct pci_dev;
struct pci_controller; struct pci_controller;
/*
* The following categories are defined:
*
* CORE: Used in the generic drm code: drm_ioctl.c, drm_mm.c, drm_memory.c, ...
* This is the category used by the DRM_DEBUG() macro.
*
* DRIVER: Used in the vendor specific part of the driver: i915, radeon, ...
* This is the category used by the DRM_DEBUG_DRIVER() macro.
*
* KMS: used in the modesetting code.
* This is the category used by the DRM_DEBUG_KMS() macro.
*
* PRIME: used in the prime code.
* This is the category used by the DRM_DEBUG_PRIME() macro.
*
* ATOMIC: used in the atomic code.
* This is the category used by the DRM_DEBUG_ATOMIC() macro.
*
* VBL: used for verbose debug message in the vblank code
* This is the category used by the DRM_DEBUG_VBL() macro.
*
* Enabling verbose debug messages is done through the drm.debug parameter,
* each category being enabled by a bit.
*
* drm.debug=0x1 will enable CORE messages
* drm.debug=0x2 will enable DRIVER messages
* drm.debug=0x3 will enable CORE and DRIVER messages
* ...
* drm.debug=0x3f will enable all messages
*
* An interesting feature is that it's possible to enable verbose logging at
* run-time by echoing the debug value in its sysfs node:
* # echo 0xf > /sys/module/drm/parameters/debug
*/
#define DRM_UT_NONE 0x00
#define DRM_UT_CORE 0x01
#define DRM_UT_DRIVER 0x02
#define DRM_UT_KMS 0x04
#define DRM_UT_PRIME 0x08
#define DRM_UT_ATOMIC 0x10
#define DRM_UT_VBL 0x20
#define DRM_UT_STATE 0x40
#define DRM_UT_LEASE 0x80
/***********************************************************************/ /***********************************************************************/
/** \name DRM template customization defaults */ /** \name DRM template customization defaults */
/*@{*/ /*@{*/
/***********************************************************************/
/** \name Macros to make printk easier */
/*@{*/
#define _DRM_PRINTK(once, level, fmt, ...) \
do { \
printk##once(KERN_##level "[" DRM_NAME "] " fmt, \
##__VA_ARGS__); \
} while (0)
#define DRM_INFO(fmt, ...) \
_DRM_PRINTK(, INFO, fmt, ##__VA_ARGS__)
#define DRM_NOTE(fmt, ...) \
_DRM_PRINTK(, NOTICE, fmt, ##__VA_ARGS__)
#define DRM_WARN(fmt, ...) \
_DRM_PRINTK(, WARNING, fmt, ##__VA_ARGS__)
#define DRM_INFO_ONCE(fmt, ...) \
_DRM_PRINTK(_once, INFO, fmt, ##__VA_ARGS__)
#define DRM_NOTE_ONCE(fmt, ...) \
_DRM_PRINTK(_once, NOTICE, fmt, ##__VA_ARGS__)
#define DRM_WARN_ONCE(fmt, ...) \
_DRM_PRINTK(_once, WARNING, fmt, ##__VA_ARGS__)
/**
* Error output.
*
* \param fmt printf() like format string.
* \param arg arguments
*/
#define DRM_DEV_ERROR(dev, fmt, ...) \
drm_dev_printk(dev, KERN_ERR, DRM_UT_NONE, __func__, " *ERROR*",\
fmt, ##__VA_ARGS__)
#define DRM_ERROR(fmt, ...) \
drm_printk(KERN_ERR, DRM_UT_NONE, fmt, ##__VA_ARGS__)
/**
* Rate limited error output. Like DRM_ERROR() but won't flood the log.
*
* \param fmt printf() like format string.
* \param arg arguments
*/
#define DRM_DEV_ERROR_RATELIMITED(dev, fmt, ...) \
({ \
static DEFINE_RATELIMIT_STATE(_rs, \
DEFAULT_RATELIMIT_INTERVAL, \
DEFAULT_RATELIMIT_BURST); \
\
if (__ratelimit(&_rs)) \
DRM_DEV_ERROR(dev, fmt, ##__VA_ARGS__); \
})
#define DRM_ERROR_RATELIMITED(fmt, ...) \
DRM_DEV_ERROR_RATELIMITED(NULL, fmt, ##__VA_ARGS__)
#define DRM_DEV_INFO(dev, fmt, ...) \
drm_dev_printk(dev, KERN_INFO, DRM_UT_NONE, __func__, "", fmt, \
##__VA_ARGS__)
#define DRM_DEV_INFO_ONCE(dev, fmt, ...) \
({ \
static bool __print_once __read_mostly; \
if (!__print_once) { \
__print_once = true; \
DRM_DEV_INFO(dev, fmt, ##__VA_ARGS__); \
} \
})
/**
* Debug output.
*
* \param fmt printf() like format string.
* \param arg arguments
*/
#define DRM_DEV_DEBUG(dev, fmt, args...) \
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_CORE, __func__, "", fmt, \
##args)
#define DRM_DEBUG(fmt, ...) \
drm_printk(KERN_DEBUG, DRM_UT_CORE, fmt, ##__VA_ARGS__)
#define DRM_DEV_DEBUG_DRIVER(dev, fmt, args...) \
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_DRIVER, __func__, "", \
fmt, ##args)
#define DRM_DEBUG_DRIVER(fmt, ...) \
drm_printk(KERN_DEBUG, DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
#define DRM_DEV_DEBUG_KMS(dev, fmt, args...) \
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_KMS, __func__, "", fmt, \
##args)
#define DRM_DEBUG_KMS(fmt, ...) \
drm_printk(KERN_DEBUG, DRM_UT_KMS, fmt, ##__VA_ARGS__)
#define DRM_DEV_DEBUG_PRIME(dev, fmt, args...) \
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_PRIME, __func__, "", \
fmt, ##args)
#define DRM_DEBUG_PRIME(fmt, ...) \
drm_printk(KERN_DEBUG, DRM_UT_PRIME, fmt, ##__VA_ARGS__)
#define DRM_DEV_DEBUG_ATOMIC(dev, fmt, args...) \
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ATOMIC, __func__, "", \
fmt, ##args)
#define DRM_DEBUG_ATOMIC(fmt, ...) \
drm_printk(KERN_DEBUG, DRM_UT_ATOMIC, fmt, ##__VA_ARGS__)
#define DRM_DEV_DEBUG_VBL(dev, fmt, args...) \
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_VBL, __func__, "", fmt, \
##args)
#define DRM_DEBUG_VBL(fmt, ...) \
drm_printk(KERN_DEBUG, DRM_UT_VBL, fmt, ##__VA_ARGS__)
#define DRM_DEBUG_LEASE(fmt, ...) \
drm_printk(KERN_DEBUG, DRM_UT_LEASE, fmt, ##__VA_ARGS__)
#define _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, level, fmt, args...) \
({ \
static DEFINE_RATELIMIT_STATE(_rs, \
DEFAULT_RATELIMIT_INTERVAL, \
DEFAULT_RATELIMIT_BURST); \
if (__ratelimit(&_rs)) \
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ ## level, \
__func__, "", fmt, ##args); \
})
/**
* Rate limited debug output. Like DRM_DEBUG() but won't flood the log.
*
* \param fmt printf() like format string.
* \param arg arguments
*/
#define DRM_DEV_DEBUG_RATELIMITED(dev, fmt, args...) \
DEV__DRM_DEFINE_DEBUG_RATELIMITED(dev, CORE, fmt, ##args)
#define DRM_DEBUG_RATELIMITED(fmt, args...) \
DRM_DEV_DEBUG_RATELIMITED(NULL, fmt, ##args)
#define DRM_DEV_DEBUG_DRIVER_RATELIMITED(dev, fmt, args...) \
_DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRIVER, fmt, ##args)
#define DRM_DEBUG_DRIVER_RATELIMITED(fmt, args...) \
DRM_DEV_DEBUG_DRIVER_RATELIMITED(NULL, fmt, ##args)
#define DRM_DEV_DEBUG_KMS_RATELIMITED(dev, fmt, args...) \
_DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, KMS, fmt, ##args)
#define DRM_DEBUG_KMS_RATELIMITED(fmt, args...) \
DRM_DEV_DEBUG_KMS_RATELIMITED(NULL, fmt, ##args)
#define DRM_DEV_DEBUG_PRIME_RATELIMITED(dev, fmt, args...) \
_DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, PRIME, fmt, ##args)
#define DRM_DEBUG_PRIME_RATELIMITED(fmt, args...) \
DRM_DEV_DEBUG_PRIME_RATELIMITED(NULL, fmt, ##args)
/* Format strings and argument splitters to simplify printing
* various "complex" objects
*/
/*@}*/
/***********************************************************************/ /***********************************************************************/
/** \name Internal types and structures */ /** \name Internal types and structures */
/*@{*/ /*@{*/
#define DRM_IF_VERSION(maj, min) (maj << 16 | min) #define DRM_IF_VERSION(maj, min) (maj << 16 | min)
/** /**
* drm_drv_uses_atomic_modeset - check if the driver implements * drm_drv_uses_atomic_modeset - check if the driver implements
* atomic_commit() * atomic_commit()

View File

@ -38,6 +38,13 @@ struct drm_private_state;
int drm_atomic_helper_check_modeset(struct drm_device *dev, int drm_atomic_helper_check_modeset(struct drm_device *dev,
struct drm_atomic_state *state); struct drm_atomic_state *state);
int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
const struct drm_crtc_state *crtc_state,
const struct drm_rect *clip,
int min_scale,
int max_scale,
bool can_position,
bool can_update_disabled);
int drm_atomic_helper_check_planes(struct drm_device *dev, int drm_atomic_helper_check_planes(struct drm_device *dev,
struct drm_atomic_state *state); struct drm_atomic_state *state);
int drm_atomic_helper_check(struct drm_device *dev, int drm_atomic_helper_check(struct drm_device *dev,

View File

@ -269,6 +269,11 @@ struct drm_display_info {
*/ */
bool dvi_dual; bool dvi_dual;
/**
* @has_hdmi_infoframe: Does the sink support the HDMI infoframe?
*/
bool has_hdmi_infoframe;
/** /**
* @edid_hdmi_dc_modes: Mask of supported hdmi deep color modes. Even * @edid_hdmi_dc_modes: Mask of supported hdmi deep color modes. Even
* more stuff redundant with @bus_formats. * more stuff redundant with @bus_formats.
@ -704,7 +709,6 @@ struct drm_cmdline_mode {
* @force: a DRM_FORCE_<foo> state for forced mode sets * @force: a DRM_FORCE_<foo> state for forced mode sets
* @override_edid: has the EDID been overwritten through debugfs for testing? * @override_edid: has the EDID been overwritten through debugfs for testing?
* @encoder_ids: valid encoders for this connector * @encoder_ids: valid encoders for this connector
* @encoder: encoder driving this connector, if any
* @eld: EDID-like data, if present * @eld: EDID-like data, if present
* @latency_present: AV delay info from ELD, if found * @latency_present: AV delay info from ELD, if found
* @video_latency: video latency info from ELD, if found * @video_latency: video latency info from ELD, if found
@ -874,7 +878,13 @@ struct drm_connector {
#define DRM_CONNECTOR_MAX_ENCODER 3 #define DRM_CONNECTOR_MAX_ENCODER 3
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
struct drm_encoder *encoder; /* currently active encoder */ /**
* @encoder: Currently bound encoder driving this connector, if any.
* Only really meaningful for non-atomic drivers. Atomic drivers should
* instead look at &drm_connector_state.best_encoder, and in case they
* need the CRTC driving this output, &drm_connector_state.crtc.
*/
struct drm_encoder *encoder;
#define MAX_ELD_BYTES 128 #define MAX_ELD_BYTES 128
/* EDID bits */ /* EDID bits */

View File

@ -17,6 +17,7 @@ struct drm_vblank_crtc;
struct drm_sg_mem; struct drm_sg_mem;
struct drm_local_map; struct drm_local_map;
struct drm_vma_offset_manager; struct drm_vma_offset_manager;
struct drm_fb_helper;
struct inode; struct inode;
@ -185,6 +186,14 @@ struct drm_device {
struct drm_vma_offset_manager *vma_offset_manager; struct drm_vma_offset_manager *vma_offset_manager;
/*@} */ /*@} */
int switch_power_state; int switch_power_state;
/**
* @fb_helper:
*
* Pointer to the fbdev emulation structure.
* Set by drm_fb_helper_init() and cleared by drm_fb_helper_fini().
*/
struct drm_fb_helper *fb_helper;
}; };
#endif #endif

View File

@ -635,6 +635,7 @@
# define DP_SET_POWER_D0 0x1 # define DP_SET_POWER_D0 0x1
# define DP_SET_POWER_D3 0x2 # define DP_SET_POWER_D3 0x2
# define DP_SET_POWER_MASK 0x3 # define DP_SET_POWER_MASK 0x3
# define DP_SET_POWER_D3_AUX_ON 0x5
#define DP_EDP_DPCD_REV 0x700 /* eDP 1.2 */ #define DP_EDP_DPCD_REV 0x700 /* eDP 1.2 */
# define DP_EDP_11 0x00 # define DP_EDP_11 0x00

View File

@ -39,6 +39,7 @@ struct drm_minor;
struct dma_buf_attachment; struct dma_buf_attachment;
struct drm_display_mode; struct drm_display_mode;
struct drm_mode_create_dumb; struct drm_mode_create_dumb;
struct drm_printer;
/* driver capabilities and requirements mask */ /* driver capabilities and requirements mask */
#define DRIVER_USE_AGP 0x1 #define DRIVER_USE_AGP 0x1
@ -428,6 +429,20 @@ struct drm_driver {
*/ */
void (*gem_close_object) (struct drm_gem_object *, struct drm_file *); void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
/**
* @gem_print_info:
*
* If driver subclasses struct &drm_gem_object, it can implement this
* optional hook for printing additional driver specific info.
*
* drm_printf_indent() should be used in the callback passing it the
* indent argument.
*
* This callback is called from drm_gem_print_info().
*/
void (*gem_print_info)(struct drm_printer *p, unsigned int indent,
const struct drm_gem_object *obj);
/** /**
* @gem_create_object: constructor for gem objects * @gem_create_object: constructor for gem objects
* *
@ -592,13 +607,6 @@ struct drm_driver {
int dev_priv_size; int dev_priv_size;
}; };
__printf(6, 7)
void drm_dev_printk(const struct device *dev, const char *level,
unsigned int category, const char *function_name,
const char *prefix, const char *format, ...);
__printf(3, 4)
void drm_printk(const char *level, unsigned int category,
const char *format, ...);
extern unsigned int drm_debug; extern unsigned int drm_debug;
int drm_dev_init(struct drm_device *dev, int drm_dev_init(struct drm_device *dev,

View File

@ -333,7 +333,6 @@ struct drm_encoder;
struct drm_connector; struct drm_connector;
struct drm_display_mode; struct drm_display_mode;
void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid);
int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads); int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads);
int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb); int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb);
int drm_av_sync_delay(struct drm_connector *connector, int drm_av_sync_delay(struct drm_connector *connector,
@ -357,6 +356,7 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
bool is_hdmi2_sink); bool is_hdmi2_sink);
int int
drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
struct drm_connector *connector,
const struct drm_display_mode *mode); const struct drm_display_mode *mode);
void void
drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame, drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame,

View File

@ -88,7 +88,6 @@ struct drm_encoder_funcs {
* @head: list management * @head: list management
* @base: base KMS object * @base: base KMS object
* @name: human readable name, can be overwritten by the driver * @name: human readable name, can be overwritten by the driver
* @crtc: currently bound CRTC
* @bridge: bridge associated to the encoder * @bridge: bridge associated to the encoder
* @funcs: control functions * @funcs: control functions
* @helper_private: mid-layer private data * @helper_private: mid-layer private data
@ -166,6 +165,11 @@ struct drm_encoder {
*/ */
uint32_t possible_clones; uint32_t possible_clones;
/**
* @crtc: Currently bound CRTC, only really meaningful for non-atomic
* drivers. Atomic drivers should instead check
* &drm_connector_state.crtc.
*/
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct drm_bridge *bridge; struct drm_bridge *bridge;
const struct drm_encoder_funcs *funcs; const struct drm_encoder_funcs *funcs;

View File

@ -36,11 +36,5 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
struct drm_plane_state *state, struct drm_plane_state *state,
unsigned int plane); unsigned int plane);
#ifdef CONFIG_DEBUG_FS
struct seq_file;
int drm_fb_cma_debugfs_show(struct seq_file *m, void *arg);
#endif
#endif #endif

View File

@ -310,6 +310,9 @@ drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn);
int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector); int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector);
int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
struct drm_connector *connector); struct drm_connector *connector);
void drm_fb_helper_lastclose(struct drm_device *dev);
void drm_fb_helper_output_poll_changed(struct drm_device *dev);
#else #else
static inline void drm_fb_helper_prepare(struct drm_device *dev, static inline void drm_fb_helper_prepare(struct drm_device *dev,
struct drm_fb_helper *helper, struct drm_fb_helper *helper,
@ -507,6 +510,14 @@ drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
return 0; return 0;
} }
static inline void drm_fb_helper_lastclose(struct drm_device *dev)
{
}
static inline void drm_fb_helper_output_poll_changed(struct drm_device *dev)
{
}
#endif #endif
static inline int static inline int

View File

@ -264,7 +264,7 @@ static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
* *
* This functions returns the framebuffer's reference count. * This functions returns the framebuffer's reference count.
*/ */
static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb) static inline uint32_t drm_framebuffer_read_refcount(const struct drm_framebuffer *fb)
{ {
return kref_read(&fb->base.refcount); return kref_read(&fb->base.refcount);
} }

Some files were not shown because too many files have changed in this diff Show More