Merge tag 'drm-misc-next-2016-11-29' of git://anongit.freedesktop.org/git/drm-misc into drm-next
Big thing is that drm-misc is now officially a group maintainer/committer model thing, with MAINTAINERS suitably updated. Otherwise just the usual pile of misc things all over, nothing that stands out this time around. * tag 'drm-misc-next-2016-11-29' of git://anongit.freedesktop.org/git/drm-misc: (33 commits) drm: Introduce drm_framebuffer_assign() drm/bridge: adv7511: Enable the audio data and clock pads on adv7533 drm/bridge: adv7511: Add Audio support drm/edid: Consider alternate cea timings to be the same VIC drm/atomic: Constify drm_atomic_crtc_needs_modeset() drm: bridge: dw-hdmi: add ASoC dependency drm: Fix shift operations for drm_fb_helper::drm_target_preferred() drm: Avoid NULL dereference for DRM_LEGACY debug message drm: Use u64_to_user_ptr() helper for blob ioctls drm: Fix conflicting macro parameter in drm_mm_for_each_node_in_range() drm: Fixup kernel doc for driver->gem_create_object drm/hisilicon/hibmc: mark PM functions __maybe_unused drm/hisilicon/hibmc: Checking for NULL instead of IS_ERR() drm: bridge: add DesignWare HDMI I2S audio support drm: Check against color expansion in drm_mm_reserve_node() drm: Define drm_mm_for_each_node_in_range() drm/doc: Fix links in drm_property.c MAINTAINERS: Add link to drm-misc documentation vgaarb: use valid dev pointer in vgaarb_info() drm/atomic: Unconfuse the old_state mess in commmit_tail ...
This commit is contained in:
commit
a90f58311f
@ -16,6 +16,8 @@ graph bindings specified in Documentation/devicetree/bindings/graph.txt.
|
||||
- Video port 0 for RGB input
|
||||
- Video port 1 for VGA output
|
||||
|
||||
Optional properties:
|
||||
- vdd-supply: Power supply for DAC
|
||||
|
||||
Example
|
||||
-------
|
||||
|
@ -63,6 +63,9 @@ Atomic State Reset and Initialization
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
|
||||
:doc: atomic state reset and initialization
|
||||
|
||||
Helper Functions Reference
|
||||
--------------------------
|
||||
|
||||
.. kernel-doc:: include/drm/drm_atomic_helper.h
|
||||
:internal:
|
||||
|
||||
|
@ -260,6 +260,12 @@ Property Types and Blob Property Support
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_property.c
|
||||
:export:
|
||||
|
||||
Standard Connector Properties
|
||||
-----------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_connector.c
|
||||
:doc: standard connector properties
|
||||
|
||||
Plane Composition Properties
|
||||
----------------------------
|
||||
|
||||
@ -287,6 +293,12 @@ Tile Group Property
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_connector.c
|
||||
:doc: Tile group
|
||||
|
||||
Explicit Fencing Properties
|
||||
---------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
|
||||
:doc: explicit fencing properties
|
||||
|
||||
Existing KMS Properties
|
||||
-----------------------
|
||||
|
||||
|
23
MAINTAINERS
23
MAINTAINERS
@ -3911,7 +3911,7 @@ F: include/linux/dma-buf*
|
||||
F: include/linux/reservation.h
|
||||
F: include/linux/*fence.h
|
||||
F: Documentation/dma-buf-sharing.txt
|
||||
T: git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
|
||||
SYNC FILE FRAMEWORK
|
||||
M: Sumit Semwal <sumit.semwal@linaro.org>
|
||||
@ -3924,7 +3924,7 @@ F: drivers/dma-buf/sw_sync.c
|
||||
F: include/linux/sync_file.h
|
||||
F: include/uapi/linux/sync_file.h
|
||||
F: Documentation/sync_file.txt
|
||||
T: git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
|
||||
DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
|
||||
M: Vinod Koul <vinod.koul@intel.com>
|
||||
@ -4022,11 +4022,30 @@ F: Documentation/gpu/
|
||||
F: include/drm/
|
||||
F: include/uapi/drm/
|
||||
|
||||
DRM DRIVERS AND MISC GPU PATCHES
|
||||
M: Daniel Vetter <daniel.vetter@intel.com>
|
||||
M: Jani Nikula <jani.nikula@linux.intel.com>
|
||||
M: Sean Paul <seanpaul@chromium.org>
|
||||
W: https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/gpu/
|
||||
F: drivers/gpu/vga/
|
||||
F: drivers/gpu/drm/*
|
||||
F: include/drm/drm*
|
||||
F: include/uapi/drm/drm*
|
||||
|
||||
DRM DRIVER FOR AST SERVER GRAPHICS CHIPS
|
||||
M: Dave Airlie <airlied@redhat.com>
|
||||
S: Odd Fixes
|
||||
F: drivers/gpu/drm/ast/
|
||||
|
||||
DRM DRIVERS FOR BRIDGE CHIPS
|
||||
M: Archit Taneja <architt@codeaurora.org>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: drivers/gpu/drm/bridge/
|
||||
|
||||
DRM DRIVER FOR BOCHS VIRTUAL GPU
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
S: Odd Fixes
|
||||
|
@ -308,8 +308,7 @@ static unsigned int sync_file_poll(struct file *file, poll_table *wait)
|
||||
|
||||
poll_wait(file, &sync_file->wq, wait);
|
||||
|
||||
if (!poll_does_not_wait(wait) &&
|
||||
!test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) {
|
||||
if (!test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) {
|
||||
if (dma_fence_add_callback(sync_file->fence, &sync_file->cb,
|
||||
fence_check_cb_func) < 0)
|
||||
wake_up_all(&sync_file->wq);
|
||||
|
@ -39,6 +39,15 @@ config DRM_DW_HDMI_AHB_AUDIO
|
||||
Designware HDMI block. This is used in conjunction with
|
||||
the i.MX6 HDMI driver.
|
||||
|
||||
config DRM_DW_HDMI_I2S_AUDIO
|
||||
tristate "Synopsis Designware I2S Audio interface"
|
||||
depends on SND_SOC
|
||||
depends on DRM_DW_HDMI
|
||||
select SND_SOC_HDMI_CODEC
|
||||
help
|
||||
Support the I2S Audio interface which is part of the Synopsis
|
||||
Designware HDMI block.
|
||||
|
||||
config DRM_NXP_PTN3460
|
||||
tristate "NXP PTN3460 DP/LVDS bridge"
|
||||
depends on OF
|
||||
|
@ -4,6 +4,7 @@ obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
|
||||
obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
|
||||
obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
|
||||
obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
|
||||
obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
|
||||
obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
|
||||
obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
|
||||
obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
|
||||
|
@ -6,6 +6,14 @@ config DRM_I2C_ADV7511
|
||||
help
|
||||
Support for the Analog Device ADV7511(W) and ADV7513 HDMI encoders.
|
||||
|
||||
config DRM_I2C_ADV7511_AUDIO
|
||||
bool "ADV7511 HDMI Audio driver"
|
||||
depends on DRM_I2C_ADV7511 && SND_SOC
|
||||
select SND_SOC_HDMI_CODEC
|
||||
help
|
||||
Support the ADV7511 HDMI Audio interface. This is used in
|
||||
conjunction with the AV7511 HDMI driver.
|
||||
|
||||
config DRM_I2C_ADV7533
|
||||
bool "ADV7533 encoder"
|
||||
depends on DRM_I2C_ADV7511
|
||||
|
@ -1,3 +1,4 @@
|
||||
adv7511-y := adv7511_drv.o
|
||||
adv7511-$(CONFIG_DRM_I2C_ADV7511_AUDIO) += adv7511_audio.o
|
||||
adv7511-$(CONFIG_DRM_I2C_ADV7533) += adv7533.o
|
||||
obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511.o
|
||||
|
@ -309,6 +309,8 @@ struct adv7511 {
|
||||
struct drm_display_mode curr_mode;
|
||||
|
||||
unsigned int f_tmds;
|
||||
unsigned int f_audio;
|
||||
unsigned int audio_source;
|
||||
|
||||
unsigned int current_edid_segment;
|
||||
uint8_t edid_buf[256];
|
||||
@ -334,6 +336,7 @@ struct adv7511 {
|
||||
bool use_timing_gen;
|
||||
|
||||
enum adv7511_type type;
|
||||
struct platform_device *audio_pdev;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DRM_I2C_ADV7533
|
||||
@ -389,4 +392,17 @@ static inline int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DRM_I2C_ADV7511_AUDIO
|
||||
int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511);
|
||||
void adv7511_audio_exit(struct adv7511 *adv7511);
|
||||
#else /*CONFIG_DRM_I2C_ADV7511_AUDIO */
|
||||
static inline int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void adv7511_audio_exit(struct adv7511 *adv7511)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_DRM_I2C_ADV7511_AUDIO */
|
||||
|
||||
#endif /* __DRM_I2C_ADV7511_H__ */
|
||||
|
213
drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
Normal file
213
drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Analog Devices ADV7511 HDMI transmitter driver
|
||||
*
|
||||
* Copyright 2012 Analog Devices Inc.
|
||||
* Copyright (c) 2016, Linaro Limited
|
||||
*
|
||||
* Licensed under the GPL-2.
|
||||
*/
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/hdmi-codec.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "adv7511.h"
|
||||
|
||||
static void adv7511_calc_cts_n(unsigned int f_tmds, unsigned int fs,
|
||||
unsigned int *cts, unsigned int *n)
|
||||
{
|
||||
switch (fs) {
|
||||
case 32000:
|
||||
*n = 4096;
|
||||
break;
|
||||
case 44100:
|
||||
*n = 6272;
|
||||
break;
|
||||
case 48000:
|
||||
*n = 6144;
|
||||
break;
|
||||
}
|
||||
|
||||
*cts = ((f_tmds * *n) / (128 * fs)) * 1000;
|
||||
}
|
||||
|
||||
static int adv7511_update_cts_n(struct adv7511 *adv7511)
|
||||
{
|
||||
unsigned int cts = 0;
|
||||
unsigned int n = 0;
|
||||
|
||||
adv7511_calc_cts_n(adv7511->f_tmds, adv7511->f_audio, &cts, &n);
|
||||
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_N0, (n >> 16) & 0xf);
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_N1, (n >> 8) & 0xff);
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_N2, n & 0xff);
|
||||
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL0,
|
||||
(cts >> 16) & 0xf);
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL1,
|
||||
(cts >> 8) & 0xff);
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL2,
|
||||
cts & 0xff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int adv7511_hdmi_hw_params(struct device *dev, void *data,
|
||||
struct hdmi_codec_daifmt *fmt,
|
||||
struct hdmi_codec_params *hparms)
|
||||
{
|
||||
struct adv7511 *adv7511 = dev_get_drvdata(dev);
|
||||
unsigned int audio_source, i2s_format = 0;
|
||||
unsigned int invert_clock;
|
||||
unsigned int rate;
|
||||
unsigned int len;
|
||||
|
||||
switch (hparms->sample_rate) {
|
||||
case 32000:
|
||||
rate = ADV7511_SAMPLE_FREQ_32000;
|
||||
break;
|
||||
case 44100:
|
||||
rate = ADV7511_SAMPLE_FREQ_44100;
|
||||
break;
|
||||
case 48000:
|
||||
rate = ADV7511_SAMPLE_FREQ_48000;
|
||||
break;
|
||||
case 88200:
|
||||
rate = ADV7511_SAMPLE_FREQ_88200;
|
||||
break;
|
||||
case 96000:
|
||||
rate = ADV7511_SAMPLE_FREQ_96000;
|
||||
break;
|
||||
case 176400:
|
||||
rate = ADV7511_SAMPLE_FREQ_176400;
|
||||
break;
|
||||
case 192000:
|
||||
rate = ADV7511_SAMPLE_FREQ_192000;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (hparms->sample_width) {
|
||||
case 16:
|
||||
len = ADV7511_I2S_SAMPLE_LEN_16;
|
||||
break;
|
||||
case 18:
|
||||
len = ADV7511_I2S_SAMPLE_LEN_18;
|
||||
break;
|
||||
case 20:
|
||||
len = ADV7511_I2S_SAMPLE_LEN_20;
|
||||
break;
|
||||
case 24:
|
||||
len = ADV7511_I2S_SAMPLE_LEN_24;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fmt->fmt) {
|
||||
case HDMI_I2S:
|
||||
audio_source = ADV7511_AUDIO_SOURCE_I2S;
|
||||
i2s_format = ADV7511_I2S_FORMAT_I2S;
|
||||
break;
|
||||
case HDMI_RIGHT_J:
|
||||
audio_source = ADV7511_AUDIO_SOURCE_I2S;
|
||||
i2s_format = ADV7511_I2S_FORMAT_RIGHT_J;
|
||||
break;
|
||||
case HDMI_LEFT_J:
|
||||
audio_source = ADV7511_AUDIO_SOURCE_I2S;
|
||||
i2s_format = ADV7511_I2S_FORMAT_LEFT_J;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
invert_clock = fmt->bit_clk_inv;
|
||||
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_SOURCE, 0x70,
|
||||
audio_source << 4);
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG, BIT(6),
|
||||
invert_clock << 6);
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_I2S_CONFIG, 0x03,
|
||||
i2s_format);
|
||||
|
||||
adv7511->audio_source = audio_source;
|
||||
|
||||
adv7511->f_audio = hparms->sample_rate;
|
||||
|
||||
adv7511_update_cts_n(adv7511);
|
||||
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG3,
|
||||
ADV7511_AUDIO_CFG3_LEN_MASK, len);
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG,
|
||||
ADV7511_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4);
|
||||
regmap_write(adv7511->regmap, 0x73, 0x1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int audio_startup(struct device *dev, void *data)
|
||||
{
|
||||
struct adv7511 *adv7511 = dev_get_drvdata(dev);
|
||||
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
|
||||
BIT(7), 0);
|
||||
|
||||
/* hide Audio infoframe updates */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
|
||||
BIT(5), BIT(5));
|
||||
/* enable N/CTS, enable Audio sample packets */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
|
||||
BIT(5), BIT(5));
|
||||
/* enable N/CTS */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
|
||||
BIT(6), BIT(6));
|
||||
/* not copyrighted */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG1,
|
||||
BIT(5), BIT(5));
|
||||
/* enable audio infoframes */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
|
||||
BIT(3), BIT(3));
|
||||
/* AV mute disable */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(0),
|
||||
BIT(7) | BIT(6), BIT(7));
|
||||
/* use Audio infoframe updated info */
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(1),
|
||||
BIT(5), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void audio_shutdown(struct device *dev, void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct hdmi_codec_ops adv7511_codec_ops = {
|
||||
.hw_params = adv7511_hdmi_hw_params,
|
||||
.audio_shutdown = audio_shutdown,
|
||||
.audio_startup = audio_startup,
|
||||
};
|
||||
|
||||
static struct hdmi_codec_pdata codec_data = {
|
||||
.ops = &adv7511_codec_ops,
|
||||
.max_i2s_channels = 2,
|
||||
.i2s = 1,
|
||||
};
|
||||
|
||||
int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511)
|
||||
{
|
||||
adv7511->audio_pdev = platform_device_register_data(dev,
|
||||
HDMI_CODEC_DRV_NAME,
|
||||
PLATFORM_DEVID_AUTO,
|
||||
&codec_data,
|
||||
sizeof(codec_data));
|
||||
return PTR_ERR_OR_ZERO(adv7511->audio_pdev);
|
||||
}
|
||||
|
||||
void adv7511_audio_exit(struct adv7511 *adv7511)
|
||||
{
|
||||
if (adv7511->audio_pdev) {
|
||||
platform_device_unregister(adv7511->audio_pdev);
|
||||
adv7511->audio_pdev = NULL;
|
||||
}
|
||||
}
|
@ -1037,6 +1037,8 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
|
||||
goto err_unregister_cec;
|
||||
}
|
||||
|
||||
adv7511_audio_init(dev, adv7511);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_cec:
|
||||
@ -1058,6 +1060,8 @@ static int adv7511_remove(struct i2c_client *i2c)
|
||||
|
||||
drm_bridge_remove(&adv7511->bridge);
|
||||
|
||||
adv7511_audio_exit(adv7511);
|
||||
|
||||
i2c_unregister_device(adv7511->i2c_edid);
|
||||
|
||||
kfree(adv7511->edid);
|
||||
|
@ -29,6 +29,7 @@ static const struct reg_sequence adv7533_cec_fixed_registers[] = {
|
||||
{ 0x17, 0xd0 },
|
||||
{ 0x24, 0x20 },
|
||||
{ 0x57, 0x11 },
|
||||
{ 0x05, 0xc8 },
|
||||
};
|
||||
|
||||
static const struct regmap_config adv7533_cec_regmap_config = {
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
@ -23,6 +24,7 @@ struct dumb_vga {
|
||||
struct drm_connector connector;
|
||||
|
||||
struct i2c_adapter *ddc;
|
||||
struct regulator *vdd;
|
||||
};
|
||||
|
||||
static inline struct dumb_vga *
|
||||
@ -124,8 +126,30 @@ static int dumb_vga_attach(struct drm_bridge *bridge)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dumb_vga_enable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
|
||||
int ret = 0;
|
||||
|
||||
if (vga->vdd)
|
||||
ret = regulator_enable(vga->vdd);
|
||||
|
||||
if (ret)
|
||||
DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
|
||||
}
|
||||
|
||||
static void dumb_vga_disable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
|
||||
|
||||
if (vga->vdd)
|
||||
regulator_disable(vga->vdd);
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
|
||||
.attach = dumb_vga_attach,
|
||||
.enable = dumb_vga_enable,
|
||||
.disable = dumb_vga_disable,
|
||||
};
|
||||
|
||||
static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
|
||||
@ -169,6 +193,15 @@ static int dumb_vga_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, vga);
|
||||
|
||||
vga->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
|
||||
if (IS_ERR(vga->vdd)) {
|
||||
ret = PTR_ERR(vga->vdd);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
vga->vdd = NULL;
|
||||
dev_dbg(&pdev->dev, "No vdd regulator found: %d\n", ret);
|
||||
}
|
||||
|
||||
vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
|
||||
if (IS_ERR(vga->ddc)) {
|
||||
if (PTR_ERR(vga->ddc) == -ENODEV) {
|
||||
|
@ -11,4 +11,11 @@ struct dw_hdmi_audio_data {
|
||||
u8 *eld;
|
||||
};
|
||||
|
||||
struct dw_hdmi_i2s_audio_data {
|
||||
struct dw_hdmi *hdmi;
|
||||
|
||||
void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
|
||||
u8 (*read)(struct dw_hdmi *hdmi, int offset);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
141
drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c
Normal file
141
drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* dw-hdmi-i2s-audio.c
|
||||
*
|
||||
* Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <drm/bridge/dw_hdmi.h>
|
||||
|
||||
#include <sound/hdmi-codec.h>
|
||||
|
||||
#include "dw-hdmi.h"
|
||||
#include "dw-hdmi-audio.h"
|
||||
|
||||
#define DRIVER_NAME "dw-hdmi-i2s-audio"
|
||||
|
||||
static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio,
|
||||
u8 val, int offset)
|
||||
{
|
||||
struct dw_hdmi *hdmi = audio->hdmi;
|
||||
|
||||
audio->write(hdmi, val, offset);
|
||||
}
|
||||
|
||||
static inline u8 hdmi_read(struct dw_hdmi_i2s_audio_data *audio, int offset)
|
||||
{
|
||||
struct dw_hdmi *hdmi = audio->hdmi;
|
||||
|
||||
return audio->read(hdmi, offset);
|
||||
}
|
||||
|
||||
static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
|
||||
struct hdmi_codec_daifmt *fmt,
|
||||
struct hdmi_codec_params *hparms)
|
||||
{
|
||||
struct dw_hdmi_i2s_audio_data *audio = data;
|
||||
struct dw_hdmi *hdmi = audio->hdmi;
|
||||
u8 conf0 = 0;
|
||||
u8 conf1 = 0;
|
||||
u8 inputclkfs = 0;
|
||||
|
||||
/* it cares I2S only */
|
||||
if ((fmt->fmt != HDMI_I2S) ||
|
||||
(fmt->bit_clk_master | fmt->frame_clk_master)) {
|
||||
dev_err(dev, "unsupported format/settings\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
inputclkfs = HDMI_AUD_INPUTCLKFS_64FS;
|
||||
conf0 = HDMI_AUD_CONF0_I2S_ALL_ENABLE;
|
||||
|
||||
switch (hparms->sample_width) {
|
||||
case 16:
|
||||
conf1 = HDMI_AUD_CONF1_WIDTH_16;
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
conf1 = HDMI_AUD_CONF1_WIDTH_24;
|
||||
break;
|
||||
}
|
||||
|
||||
dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate);
|
||||
|
||||
hdmi_write(audio, inputclkfs, HDMI_AUD_INPUTCLKFS);
|
||||
hdmi_write(audio, conf0, HDMI_AUD_CONF0);
|
||||
hdmi_write(audio, conf1, HDMI_AUD_CONF1);
|
||||
|
||||
dw_hdmi_audio_enable(hdmi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data)
|
||||
{
|
||||
struct dw_hdmi_i2s_audio_data *audio = data;
|
||||
struct dw_hdmi *hdmi = audio->hdmi;
|
||||
|
||||
dw_hdmi_audio_disable(hdmi);
|
||||
|
||||
hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0);
|
||||
}
|
||||
|
||||
static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
|
||||
.hw_params = dw_hdmi_i2s_hw_params,
|
||||
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
|
||||
};
|
||||
|
||||
static int snd_dw_hdmi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data;
|
||||
struct platform_device_info pdevinfo;
|
||||
struct hdmi_codec_pdata pdata;
|
||||
struct platform_device *platform;
|
||||
|
||||
pdata.ops = &dw_hdmi_i2s_ops;
|
||||
pdata.i2s = 1;
|
||||
pdata.max_i2s_channels = 6;
|
||||
pdata.data = audio;
|
||||
|
||||
memset(&pdevinfo, 0, sizeof(pdevinfo));
|
||||
pdevinfo.parent = pdev->dev.parent;
|
||||
pdevinfo.id = PLATFORM_DEVID_AUTO;
|
||||
pdevinfo.name = HDMI_CODEC_DRV_NAME;
|
||||
pdevinfo.data = &pdata;
|
||||
pdevinfo.size_data = sizeof(pdata);
|
||||
pdevinfo.dma_mask = DMA_BIT_MASK(32);
|
||||
|
||||
platform = platform_device_register_full(&pdevinfo);
|
||||
if (IS_ERR(platform))
|
||||
return PTR_ERR(platform);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, platform);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_dw_hdmi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct platform_device *platform = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
platform_device_unregister(platform);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver snd_dw_hdmi_driver = {
|
||||
.probe = snd_dw_hdmi_probe,
|
||||
.remove = snd_dw_hdmi_remove,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
module_platform_driver(snd_dw_hdmi_driver);
|
||||
|
||||
MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
|
||||
MODULE_DESCRIPTION("Synopsis Designware HDMI I2S ALSA SoC interface");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:" DRIVER_NAME);
|
@ -1871,10 +1871,11 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
struct device_node *np = dev->of_node;
|
||||
struct platform_device_info pdevinfo;
|
||||
struct device_node *ddc_node;
|
||||
struct dw_hdmi_audio_data audio;
|
||||
struct dw_hdmi *hdmi;
|
||||
int ret;
|
||||
u32 val = 1;
|
||||
u8 config0;
|
||||
u8 config1;
|
||||
|
||||
hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
|
||||
if (!hdmi)
|
||||
@ -2011,7 +2012,12 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
pdevinfo.parent = dev;
|
||||
pdevinfo.id = PLATFORM_DEVID_AUTO;
|
||||
|
||||
if (hdmi_readb(hdmi, HDMI_CONFIG1_ID) & HDMI_CONFIG1_AHB) {
|
||||
config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
|
||||
config1 = hdmi_readb(hdmi, HDMI_CONFIG1_ID);
|
||||
|
||||
if (config1 & HDMI_CONFIG1_AHB) {
|
||||
struct dw_hdmi_audio_data audio;
|
||||
|
||||
audio.phys = iores->start;
|
||||
audio.base = hdmi->regs;
|
||||
audio.irq = irq;
|
||||
@ -2023,6 +2029,18 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
pdevinfo.size_data = sizeof(audio);
|
||||
pdevinfo.dma_mask = DMA_BIT_MASK(32);
|
||||
hdmi->audio = platform_device_register_full(&pdevinfo);
|
||||
} else if (config0 & HDMI_CONFIG0_I2S) {
|
||||
struct dw_hdmi_i2s_audio_data audio;
|
||||
|
||||
audio.hdmi = hdmi;
|
||||
audio.write = hdmi_writeb;
|
||||
audio.read = hdmi_readb;
|
||||
|
||||
pdevinfo.name = "dw-hdmi-i2s-audio";
|
||||
pdevinfo.data = &audio;
|
||||
pdevinfo.size_data = sizeof(audio);
|
||||
pdevinfo.dma_mask = DMA_BIT_MASK(32);
|
||||
hdmi->audio = platform_device_register_full(&pdevinfo);
|
||||
}
|
||||
|
||||
/* Reset HDMI DDC I2C master controller and mute I2CM interrupts */
|
||||
|
@ -545,6 +545,9 @@
|
||||
#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12
|
||||
|
||||
enum {
|
||||
/* CONFIG0_ID field values */
|
||||
HDMI_CONFIG0_I2S = 0x10,
|
||||
|
||||
/* CONFIG1_ID field values */
|
||||
HDMI_CONFIG1_AHB = 0x01,
|
||||
|
||||
@ -891,6 +894,17 @@ enum {
|
||||
HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08,
|
||||
HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04,
|
||||
|
||||
/* AUD_CONF0 field values */
|
||||
HDMI_AUD_CONF0_SW_RESET = 0x80,
|
||||
HDMI_AUD_CONF0_I2S_ALL_ENABLE = 0x2F,
|
||||
|
||||
/* AUD_CONF1 field values */
|
||||
HDMI_AUD_CONF1_MODE_I2S = 0x00,
|
||||
HDMI_AUD_CONF1_MODE_RIGHT_J = 0x02,
|
||||
HDMI_AUD_CONF1_MODE_LEFT_J = 0x04,
|
||||
HDMI_AUD_CONF1_WIDTH_16 = 0x10,
|
||||
HDMI_AUD_CONF1_WIDTH_24 = 0x18,
|
||||
|
||||
/* AUD_CTS3 field values */
|
||||
HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5,
|
||||
HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0,
|
||||
@ -905,6 +919,12 @@ enum {
|
||||
HDMI_AUD_CTS3_CTS_MANUAL = 0x10,
|
||||
HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f,
|
||||
|
||||
/* HDMI_AUD_INPUTCLKFS field values */
|
||||
HDMI_AUD_INPUTCLKFS_128FS = 0,
|
||||
HDMI_AUD_INPUTCLKFS_256FS = 1,
|
||||
HDMI_AUD_INPUTCLKFS_512FS = 2,
|
||||
HDMI_AUD_INPUTCLKFS_64FS = 4,
|
||||
|
||||
/* AHB_DMA_CONF0 field values */
|
||||
HDMI_AHB_DMA_CONF0_SW_FIFO_RST_OFFSET = 7,
|
||||
HDMI_AHB_DMA_CONF0_SW_FIFO_RST_MASK = 0x80,
|
||||
|
@ -965,12 +965,12 @@ static void drm_atomic_plane_print_state(struct drm_printer *p,
|
||||
|
||||
drm_printf(p, "\t\tformat=%s\n",
|
||||
drm_get_format_name(fb->pixel_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, "\t\t\tmodifier[%d]=0x%llx\n", i, fb->modifier[i]);
|
||||
}
|
||||
}
|
||||
drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest));
|
||||
@ -1246,18 +1246,14 @@ void
|
||||
drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
|
||||
struct drm_framebuffer *fb)
|
||||
{
|
||||
if (plane_state->fb)
|
||||
drm_framebuffer_unreference(plane_state->fb);
|
||||
if (fb)
|
||||
drm_framebuffer_reference(fb);
|
||||
plane_state->fb = fb;
|
||||
|
||||
if (fb)
|
||||
DRM_DEBUG_ATOMIC("Set [FB:%d] for plane state %p\n",
|
||||
fb->base.id, plane_state);
|
||||
else
|
||||
DRM_DEBUG_ATOMIC("Set [NOFB] for plane state %p\n",
|
||||
plane_state);
|
||||
|
||||
drm_framebuffer_assign(&plane_state->fb, fb);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
|
||||
|
||||
@ -1686,6 +1682,13 @@ int drm_atomic_debugfs_init(struct drm_minor *minor)
|
||||
ARRAY_SIZE(drm_atomic_debugfs_list),
|
||||
minor->debugfs_root, minor);
|
||||
}
|
||||
|
||||
int drm_atomic_debugfs_cleanup(struct drm_minor *minor)
|
||||
{
|
||||
return drm_debugfs_remove_files(drm_atomic_debugfs_list,
|
||||
ARRAY_SIZE(drm_atomic_debugfs_list),
|
||||
minor);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -1809,6 +1812,58 @@ void drm_atomic_clean_old_fb(struct drm_device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_clean_old_fb);
|
||||
|
||||
/**
|
||||
* DOC: explicit fencing properties
|
||||
*
|
||||
* Explicit fencing allows userspace to control the buffer synchronization
|
||||
* between devices. A Fence or a group of fences are transfered to/from
|
||||
* userspace using Sync File fds and there are two DRM properties for that.
|
||||
* IN_FENCE_FD on each DRM Plane to send fences to the kernel and
|
||||
* OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
|
||||
*
|
||||
* As a contrast, with implicit fencing the kernel keeps track of any
|
||||
* ongoing rendering, and automatically ensures that the atomic update waits
|
||||
* for any pending rendering to complete. For shared buffers represented with
|
||||
* a struct &dma_buf this is tracked in &reservation_object structures.
|
||||
* Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org),
|
||||
* whereas explicit fencing is what Android wants.
|
||||
*
|
||||
* "IN_FENCE_FD”:
|
||||
* Use this property to pass a fence that DRM should wait on before
|
||||
* proceeding with the Atomic Commit request and show the framebuffer for
|
||||
* the plane on the screen. The fence can be either a normal fence or a
|
||||
* merged one, the sync_file framework will handle both cases and use a
|
||||
* fence_array if a merged fence is received. Passing -1 here means no
|
||||
* fences to wait on.
|
||||
*
|
||||
* If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag
|
||||
* it will only check if the Sync File is a valid one.
|
||||
*
|
||||
* On the driver side the fence is stored on the @fence parameter of
|
||||
* struct &drm_plane_state. Drivers which also support implicit fencing
|
||||
* should set the implicit fence using drm_atomic_set_fence_for_plane(),
|
||||
* to make sure there's consistent behaviour between drivers in precedence
|
||||
* of implicit vs. explicit fencing.
|
||||
*
|
||||
* "OUT_FENCE_PTR”:
|
||||
* Use this property to pass a file descriptor pointer to DRM. Once the
|
||||
* Atomic Commit request call returns OUT_FENCE_PTR will be filled with
|
||||
* the file descriptor number of a Sync File. This Sync File contains the
|
||||
* CRTC fence that will be signaled when all framebuffers present on the
|
||||
* Atomic Commit * request for that given CRTC are scanned out on the
|
||||
* screen.
|
||||
*
|
||||
* The Atomic Commit request fails if a invalid pointer is passed. If the
|
||||
* Atomic Commit request fails for any other reason the out fence fd
|
||||
* returned will be -1. On a Atomic Commit with the
|
||||
* DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
|
||||
*
|
||||
* Note that out-fences don't have a special interface to drivers and are
|
||||
* internally represented by a struct &drm_pending_vblank_event in struct
|
||||
* &drm_crtc_state, which is also used by the nonblocking atomic commit
|
||||
* helpers and for the DRM event handling for existing userspace.
|
||||
*/
|
||||
|
||||
static struct dma_fence *get_crtc_fence(struct drm_crtc *crtc)
|
||||
{
|
||||
struct dma_fence *fence;
|
||||
|
@ -1006,13 +1006,21 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables);
|
||||
* drm_atomic_helper_wait_for_fences - wait for fences stashed in plane state
|
||||
* @dev: DRM device
|
||||
* @state: atomic state object with old state structures
|
||||
* @pre_swap: if true, do an interruptible wait
|
||||
* @pre_swap: If true, do an interruptible wait, and @state is the new state.
|
||||
* Otherwise @state is the old state.
|
||||
*
|
||||
* For implicit sync, driver should fish the exclusive fence out from the
|
||||
* incoming fb's and stash it in the drm_plane_state. This is called after
|
||||
* drm_atomic_helper_swap_state() so it uses the current plane state (and
|
||||
* just uses the atomic state to find the changed planes)
|
||||
*
|
||||
* Note that @pre_swap is needed since the point where we block for fences moves
|
||||
* around depending upon whether an atomic commit is blocking or
|
||||
* non-blocking. For async commit all waiting needs to happen after
|
||||
* drm_atomic_helper_swap_state() is called, but for synchronous commits we want
|
||||
* to wait **before** we do anything that can't be easily rolled back. That is
|
||||
* before we call drm_atomic_helper_swap_state().
|
||||
*
|
||||
* Returns zero if success or < 0 if dma_fence_wait() fails.
|
||||
*/
|
||||
int drm_atomic_helper_wait_for_fences(struct drm_device *dev,
|
||||
@ -1147,7 +1155,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_commit_tail - commit atomic update to hardware
|
||||
* @state: new modeset state to be committed
|
||||
* @old_state: atomic state object with old state structures
|
||||
*
|
||||
* This is the default implemenation for the ->atomic_commit_tail() hook of the
|
||||
* &drm_mode_config_helper_funcs vtable.
|
||||
@ -1158,53 +1166,53 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
|
||||
*
|
||||
* For drivers supporting runtime PM the recommended sequence is instead ::
|
||||
*
|
||||
* drm_atomic_helper_commit_modeset_disables(dev, state);
|
||||
* drm_atomic_helper_commit_modeset_disables(dev, old_state);
|
||||
*
|
||||
* drm_atomic_helper_commit_modeset_enables(dev, state);
|
||||
* drm_atomic_helper_commit_modeset_enables(dev, old_state);
|
||||
*
|
||||
* drm_atomic_helper_commit_planes(dev, state,
|
||||
* drm_atomic_helper_commit_planes(dev, old_state,
|
||||
* DRM_PLANE_COMMIT_ACTIVE_ONLY);
|
||||
*
|
||||
* for committing the atomic update to hardware. See the kerneldoc entries for
|
||||
* these three functions for more details.
|
||||
*/
|
||||
void drm_atomic_helper_commit_tail(struct drm_atomic_state *state)
|
||||
void drm_atomic_helper_commit_tail(struct drm_atomic_state *old_state)
|
||||
{
|
||||
struct drm_device *dev = state->dev;
|
||||
struct drm_device *dev = old_state->dev;
|
||||
|
||||
drm_atomic_helper_commit_modeset_disables(dev, state);
|
||||
drm_atomic_helper_commit_modeset_disables(dev, old_state);
|
||||
|
||||
drm_atomic_helper_commit_planes(dev, state, 0);
|
||||
drm_atomic_helper_commit_planes(dev, old_state, 0);
|
||||
|
||||
drm_atomic_helper_commit_modeset_enables(dev, state);
|
||||
drm_atomic_helper_commit_modeset_enables(dev, old_state);
|
||||
|
||||
drm_atomic_helper_commit_hw_done(state);
|
||||
drm_atomic_helper_commit_hw_done(old_state);
|
||||
|
||||
drm_atomic_helper_wait_for_vblanks(dev, state);
|
||||
drm_atomic_helper_wait_for_vblanks(dev, old_state);
|
||||
|
||||
drm_atomic_helper_cleanup_planes(dev, state);
|
||||
drm_atomic_helper_cleanup_planes(dev, old_state);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_commit_tail);
|
||||
|
||||
static void commit_tail(struct drm_atomic_state *state)
|
||||
static void commit_tail(struct drm_atomic_state *old_state)
|
||||
{
|
||||
struct drm_device *dev = state->dev;
|
||||
struct drm_device *dev = old_state->dev;
|
||||
struct drm_mode_config_helper_funcs *funcs;
|
||||
|
||||
funcs = dev->mode_config.helper_private;
|
||||
|
||||
drm_atomic_helper_wait_for_fences(dev, state, false);
|
||||
drm_atomic_helper_wait_for_fences(dev, old_state, false);
|
||||
|
||||
drm_atomic_helper_wait_for_dependencies(state);
|
||||
drm_atomic_helper_wait_for_dependencies(old_state);
|
||||
|
||||
if (funcs && funcs->atomic_commit_tail)
|
||||
funcs->atomic_commit_tail(state);
|
||||
funcs->atomic_commit_tail(old_state);
|
||||
else
|
||||
drm_atomic_helper_commit_tail(state);
|
||||
drm_atomic_helper_commit_tail(old_state);
|
||||
|
||||
drm_atomic_helper_commit_cleanup_done(state);
|
||||
drm_atomic_helper_commit_cleanup_done(old_state);
|
||||
|
||||
drm_atomic_state_put(state);
|
||||
drm_atomic_state_put(old_state);
|
||||
}
|
||||
|
||||
static void commit_work(struct work_struct *work)
|
||||
@ -1498,10 +1506,10 @@ static struct drm_crtc_commit *preceeding_commit(struct drm_crtc *crtc)
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_wait_for_dependencies - wait for required preceeding commits
|
||||
* @state: new modeset state to be committed
|
||||
* @old_state: atomic state object with old state structures
|
||||
*
|
||||
* This function waits for all preceeding commits that touch the same CRTC as
|
||||
* @state to both be committed to the hardware (as signalled by
|
||||
* @old_state to both be committed to the hardware (as signalled by
|
||||
* drm_atomic_helper_commit_hw_done) and executed by the hardware (as signalled
|
||||
* by calling drm_crtc_vblank_send_event on the event member of
|
||||
* &drm_crtc_state).
|
||||
@ -1509,7 +1517,7 @@ static struct drm_crtc_commit *preceeding_commit(struct drm_crtc *crtc)
|
||||
* This is part of the atomic helper support for nonblocking commits, see
|
||||
* drm_atomic_helper_setup_commit() for an overview.
|
||||
*/
|
||||
void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *state)
|
||||
void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
@ -1517,7 +1525,7 @@ void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *state)
|
||||
int i;
|
||||
long ret;
|
||||
|
||||
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
for_each_crtc_in_state(old_state, crtc, crtc_state, i) {
|
||||
spin_lock(&crtc->commit_lock);
|
||||
commit = preceeding_commit(crtc);
|
||||
if (commit)
|
||||
@ -1548,7 +1556,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_commit_hw_done - setup possible nonblocking commit
|
||||
* @state: new modeset state to be committed
|
||||
* @old_state: atomic state object with old state structures
|
||||
*
|
||||
* This function is used to signal completion of the hardware commit step. After
|
||||
* this step the driver is not allowed to read or change any permanent software
|
||||
@ -1561,15 +1569,15 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies);
|
||||
* This is part of the atomic helper support for nonblocking commits, see
|
||||
* drm_atomic_helper_setup_commit() for an overview.
|
||||
*/
|
||||
void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *state)
|
||||
void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_crtc_commit *commit;
|
||||
int i;
|
||||
|
||||
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
commit = state->crtcs[i].commit;
|
||||
for_each_crtc_in_state(old_state, crtc, crtc_state, i) {
|
||||
commit = old_state->crtcs[i].commit;
|
||||
if (!commit)
|
||||
continue;
|
||||
|
||||
@ -1584,16 +1592,16 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_commit_cleanup_done - signal completion of commit
|
||||
* @state: new modeset state to be committed
|
||||
* @old_state: atomic state object with old state structures
|
||||
*
|
||||
* This signals completion of the atomic update @state, including any cleanup
|
||||
* work. If used, it must be called right before calling
|
||||
* This signals completion of the atomic update @old_state, including any
|
||||
* cleanup work. If used, it must be called right before calling
|
||||
* drm_atomic_state_put().
|
||||
*
|
||||
* This is part of the atomic helper support for nonblocking commits, see
|
||||
* drm_atomic_helper_setup_commit() for an overview.
|
||||
*/
|
||||
void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *state)
|
||||
void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
@ -1601,8 +1609,8 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *state)
|
||||
int i;
|
||||
long ret;
|
||||
|
||||
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
commit = state->crtcs[i].commit;
|
||||
for_each_crtc_in_state(old_state, crtc, crtc_state, i) {
|
||||
commit = old_state->crtcs[i].commit;
|
||||
if (WARN_ON(!commit))
|
||||
continue;
|
||||
|
||||
|
@ -588,6 +588,50 @@ static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = {
|
||||
DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
|
||||
drm_tv_subconnector_enum_list)
|
||||
|
||||
/**
|
||||
* DOC: standard connector properties
|
||||
*
|
||||
* DRM connectors have a few standardized properties:
|
||||
*
|
||||
* EDID:
|
||||
* Blob property which contains the current EDID read from the sink. This
|
||||
* is useful to parse sink identification information like vendor, model
|
||||
* and serial. Drivers should update this property by calling
|
||||
* drm_mode_connector_update_edid_property(), usually after having parsed
|
||||
* the EDID using drm_add_edid_modes(). Userspace cannot change this
|
||||
* property.
|
||||
* DPMS:
|
||||
* Legacy property for setting the power state of the connector. For atomic
|
||||
* drivers this is only provided for backwards compatibility with existing
|
||||
* drivers, it remaps to controlling the "ACTIVE" property on the CRTC the
|
||||
* connector is linked to. Drivers should never set this property directly,
|
||||
* it is handled by the DRM core by calling the ->dpms() callback in
|
||||
* &drm_connector_funcs. Atomic drivers should implement this hook using
|
||||
* drm_atomic_helper_connector_dpms(). This is the only property standard
|
||||
* connector property that userspace can change.
|
||||
* PATH:
|
||||
* Connector path property to identify how this sink is physically
|
||||
* connected. Used by DP MST. This should be set by calling
|
||||
* drm_mode_connector_set_path_property(), in the case of DP MST with the
|
||||
* path property the MST manager created. Userspace cannot change this
|
||||
* property.
|
||||
* TILE:
|
||||
* Connector tile group property to indicate how a set of DRM connector
|
||||
* compose together into one logical screen. This is used by both high-res
|
||||
* external screens (often only using a single cable, but exposing multiple
|
||||
* DP MST sinks), or high-res integrated panels (like dual-link DSI) which
|
||||
* are not gen-locked. Note that for tiled panels which are genlocked, like
|
||||
* dual-link LVDS or dual-link DSI, the driver should try to not expose the
|
||||
* tiling and virtualize both &drm_crtc and &drm_plane if needed. Drivers
|
||||
* should update this value using drm_mode_connector_set_tile_property().
|
||||
* Userspace cannot change this property.
|
||||
*
|
||||
* Connectors also have one standardized atomic property:
|
||||
*
|
||||
* CRTC_ID:
|
||||
* Mode object ID of the &drm_crtc this connector should be connected to.
|
||||
*/
|
||||
|
||||
int drm_connector_create_standard_properties(struct drm_device *dev)
|
||||
{
|
||||
struct drm_property *prop;
|
||||
|
@ -228,6 +228,7 @@ EXPORT_SYMBOL(drm_debugfs_remove_files);
|
||||
int drm_debugfs_cleanup(struct drm_minor *minor)
|
||||
{
|
||||
struct drm_device *dev = minor->dev;
|
||||
int ret;
|
||||
|
||||
if (!minor->debugfs_root)
|
||||
return 0;
|
||||
@ -235,6 +236,14 @@ int drm_debugfs_cleanup(struct drm_minor *minor)
|
||||
if (dev->driver->debugfs_cleanup)
|
||||
dev->driver->debugfs_cleanup(minor);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
|
||||
ret = drm_atomic_debugfs_cleanup(minor);
|
||||
if (ret) {
|
||||
DRM_ERROR("DRM: Failed to remove atomic debugfs entries\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
drm_debugfs_remove_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES, minor);
|
||||
|
||||
debugfs_remove(minor->debugfs_root);
|
||||
|
@ -497,12 +497,6 @@ int drm_dev_init(struct drm_device *dev,
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL);
|
||||
if (ret)
|
||||
goto err_minors;
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_RENDER)) {
|
||||
ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
|
||||
if (ret)
|
||||
|
@ -2613,6 +2613,41 @@ cea_mode_alternate_clock(const struct drm_display_mode *cea_mode)
|
||||
return clock;
|
||||
}
|
||||
|
||||
static bool
|
||||
cea_mode_alternate_timings(u8 vic, struct drm_display_mode *mode)
|
||||
{
|
||||
/*
|
||||
* For certain VICs the spec allows the vertical
|
||||
* front porch to vary by one or two lines.
|
||||
*
|
||||
* cea_modes[] stores the variant with the shortest
|
||||
* vertical front porch. We can adjust the mode to
|
||||
* get the other variants by simply increasing the
|
||||
* vertical front porch length.
|
||||
*/
|
||||
BUILD_BUG_ON(edid_cea_modes[8].vtotal != 262 ||
|
||||
edid_cea_modes[9].vtotal != 262 ||
|
||||
edid_cea_modes[12].vtotal != 262 ||
|
||||
edid_cea_modes[13].vtotal != 262 ||
|
||||
edid_cea_modes[23].vtotal != 312 ||
|
||||
edid_cea_modes[24].vtotal != 312 ||
|
||||
edid_cea_modes[27].vtotal != 312 ||
|
||||
edid_cea_modes[28].vtotal != 312);
|
||||
|
||||
if (((vic == 8 || vic == 9 ||
|
||||
vic == 12 || vic == 13) && mode->vtotal < 263) ||
|
||||
((vic == 23 || vic == 24 ||
|
||||
vic == 27 || vic == 28) && mode->vtotal < 314)) {
|
||||
mode->vsync_start++;
|
||||
mode->vsync_end++;
|
||||
mode->vtotal++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode *to_match,
|
||||
unsigned int clock_tolerance)
|
||||
{
|
||||
@ -2622,19 +2657,21 @@ static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode *to_m
|
||||
return 0;
|
||||
|
||||
for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
|
||||
const struct drm_display_mode *cea_mode = &edid_cea_modes[vic];
|
||||
struct drm_display_mode cea_mode = edid_cea_modes[vic];
|
||||
unsigned int clock1, clock2;
|
||||
|
||||
/* Check both 60Hz and 59.94Hz */
|
||||
clock1 = cea_mode->clock;
|
||||
clock2 = cea_mode_alternate_clock(cea_mode);
|
||||
clock1 = cea_mode.clock;
|
||||
clock2 = cea_mode_alternate_clock(&cea_mode);
|
||||
|
||||
if (abs(to_match->clock - clock1) > clock_tolerance &&
|
||||
abs(to_match->clock - clock2) > clock_tolerance)
|
||||
continue;
|
||||
|
||||
if (drm_mode_equal_no_clocks(to_match, cea_mode))
|
||||
return vic;
|
||||
do {
|
||||
if (drm_mode_equal_no_clocks_no_stereo(to_match, &cea_mode))
|
||||
return vic;
|
||||
} while (cea_mode_alternate_timings(vic, &cea_mode));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2655,18 +2692,23 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
|
||||
return 0;
|
||||
|
||||
for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
|
||||
const struct drm_display_mode *cea_mode = &edid_cea_modes[vic];
|
||||
struct drm_display_mode cea_mode = edid_cea_modes[vic];
|
||||
unsigned int clock1, clock2;
|
||||
|
||||
/* Check both 60Hz and 59.94Hz */
|
||||
clock1 = cea_mode->clock;
|
||||
clock2 = cea_mode_alternate_clock(cea_mode);
|
||||
clock1 = cea_mode.clock;
|
||||
clock2 = cea_mode_alternate_clock(&cea_mode);
|
||||
|
||||
if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
|
||||
KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
|
||||
drm_mode_equal_no_clocks_no_stereo(to_match, cea_mode))
|
||||
return vic;
|
||||
if (KHZ2PICOS(to_match->clock) != KHZ2PICOS(clock1) &&
|
||||
KHZ2PICOS(to_match->clock) != KHZ2PICOS(clock2))
|
||||
continue;
|
||||
|
||||
do {
|
||||
if (drm_mode_equal_no_clocks_no_stereo(to_match, &cea_mode))
|
||||
return vic;
|
||||
} while (cea_mode_alternate_timings(vic, &cea_mode));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_match_cea_mode);
|
||||
|
@ -1959,19 +1959,20 @@ static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
|
||||
bool *enabled, int width, int height)
|
||||
{
|
||||
struct drm_fb_helper_connector *fb_helper_conn;
|
||||
int i;
|
||||
uint64_t conn_configured = 0, mask;
|
||||
const u64 mask = BIT_ULL(fb_helper->connector_count) - 1;
|
||||
u64 conn_configured = 0;
|
||||
int tile_pass = 0;
|
||||
mask = (1 << fb_helper->connector_count) - 1;
|
||||
int i;
|
||||
|
||||
retry:
|
||||
for (i = 0; i < fb_helper->connector_count; i++) {
|
||||
fb_helper_conn = fb_helper->connector_info[i];
|
||||
|
||||
if (conn_configured & (1 << i))
|
||||
if (conn_configured & BIT_ULL(i))
|
||||
continue;
|
||||
|
||||
if (enabled[i] == false) {
|
||||
conn_configured |= (1 << i);
|
||||
conn_configured |= BIT_ULL(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2012,7 +2013,7 @@ retry:
|
||||
}
|
||||
DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
|
||||
"none");
|
||||
conn_configured |= (1 << i);
|
||||
conn_configured |= BIT_ULL(i);
|
||||
}
|
||||
|
||||
if ((conn_configured & mask) != mask) {
|
||||
|
@ -177,6 +177,13 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (r->flags & DRM_MODE_FB_MODIFIERS &&
|
||||
r->modifier[i] != r->modifier[0]) {
|
||||
DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
|
||||
r->modifier[i], i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* modifier specific checks: */
|
||||
switch (r->modifier[i]) {
|
||||
case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
|
||||
|
@ -176,7 +176,8 @@ int drm_legacy_lock(struct drm_device *dev, void *data,
|
||||
|
||||
DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
|
||||
lock->context, task_pid_nr(current),
|
||||
master->lock.hw_lock->lock, lock->flags);
|
||||
master->lock.hw_lock ? master->lock.hw_lock->lock : -1,
|
||||
lock->flags);
|
||||
|
||||
add_wait_queue(&master->lock.lock_queue, &entry);
|
||||
spin_lock_bh(&master->lock.spinlock);
|
||||
|
@ -174,19 +174,12 @@ INTERVAL_TREE_DEFINE(struct drm_mm_node, rb,
|
||||
START, LAST, static inline, drm_mm_interval_tree)
|
||||
|
||||
struct drm_mm_node *
|
||||
drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last)
|
||||
__drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last)
|
||||
{
|
||||
return drm_mm_interval_tree_iter_first(&mm->interval_tree,
|
||||
start, last);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_interval_first);
|
||||
|
||||
struct drm_mm_node *
|
||||
drm_mm_interval_next(struct drm_mm_node *node, u64 start, u64 last)
|
||||
{
|
||||
return drm_mm_interval_tree_iter_next(node, start, last);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_interval_next);
|
||||
EXPORT_SYMBOL(__drm_mm_interval_first);
|
||||
|
||||
static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node,
|
||||
struct drm_mm_node *node)
|
||||
@ -313,6 +306,7 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
|
||||
u64 end = node->start + node->size;
|
||||
struct drm_mm_node *hole;
|
||||
u64 hole_start, hole_end;
|
||||
u64 adj_start, adj_end;
|
||||
|
||||
if (WARN_ON(node->size == 0))
|
||||
return -EINVAL;
|
||||
@ -334,9 +328,13 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
|
||||
if (!hole->hole_follows)
|
||||
return -ENOSPC;
|
||||
|
||||
hole_start = __drm_mm_hole_node_start(hole);
|
||||
hole_end = __drm_mm_hole_node_end(hole);
|
||||
if (hole_start > node->start || hole_end < end)
|
||||
adj_start = hole_start = __drm_mm_hole_node_start(hole);
|
||||
adj_end = hole_end = __drm_mm_hole_node_end(hole);
|
||||
|
||||
if (mm->color_adjust)
|
||||
mm->color_adjust(hole, node->color, &adj_start, &adj_end);
|
||||
|
||||
if (adj_start > node->start || adj_end < end)
|
||||
return -ENOSPC;
|
||||
|
||||
node->mm = mm;
|
||||
|
@ -38,7 +38,7 @@
|
||||
* Some userspace presumes that the first connected connector is the main
|
||||
* display, where it's supposed to display e.g. the login screen. For
|
||||
* laptops, this should be the main panel. Use this function to sort all
|
||||
* (eDP/LVDS) panels to the front of the connector list, instead of
|
||||
* (eDP/LVDS/DSI) panels to the front of the connector list, instead of
|
||||
* painstakingly trying to initialize them in the right order.
|
||||
*/
|
||||
void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
|
||||
@ -51,7 +51,8 @@ void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
|
||||
list_for_each_entry_safe(connector, tmp,
|
||||
&dev->mode_config.connector_list, head) {
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
|
||||
connector->connector_type == DRM_MODE_CONNECTOR_eDP)
|
||||
connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
|
||||
connector->connector_type == DRM_MODE_CONNECTOR_DSI)
|
||||
list_move_tail(&connector->head, &panel_list);
|
||||
}
|
||||
|
||||
@ -93,8 +94,8 @@ void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
|
||||
for (i = 0; i < 4; i++) {
|
||||
fb->pitches[i] = mode_cmd->pitches[i];
|
||||
fb->offsets[i] = mode_cmd->offsets[i];
|
||||
fb->modifier[i] = mode_cmd->modifier[i];
|
||||
}
|
||||
fb->modifier = mode_cmd->modifier[0];
|
||||
fb->pixel_format = mode_cmd->pixel_format;
|
||||
fb->flags = mode_cmd->flags;
|
||||
}
|
||||
|
@ -65,9 +65,9 @@ static bool drm_property_type_valid(struct drm_property *property)
|
||||
* @num_values: number of pre-defined values
|
||||
*
|
||||
* This creates a new generic drm property which can then be attached to a drm
|
||||
* object with drm_object_attach_property. The returned property object must be
|
||||
* freed with drm_property_destroy(), which is done automatically when calling
|
||||
* drm_mode_config_cleanup().
|
||||
* object with drm_object_attach_property(). The returned property object must
|
||||
* be freed with drm_property_destroy(), which is done automatically when
|
||||
* calling drm_mode_config_cleanup().
|
||||
*
|
||||
* Returns:
|
||||
* A pointer to the newly created property on success, NULL on failure.
|
||||
@ -125,9 +125,9 @@ EXPORT_SYMBOL(drm_property_create);
|
||||
* @num_values: number of pre-defined values
|
||||
*
|
||||
* This creates a new generic drm property which can then be attached to a drm
|
||||
* object with drm_object_attach_property. The returned property object must be
|
||||
* freed with drm_property_destroy(), which is done automatically when calling
|
||||
* drm_mode_config_cleanup().
|
||||
* object with drm_object_attach_property(). The returned property object must
|
||||
* be freed with drm_property_destroy(), which is done automatically when
|
||||
* calling drm_mode_config_cleanup().
|
||||
*
|
||||
* Userspace is only allowed to set one of the predefined values for enumeration
|
||||
* properties.
|
||||
@ -173,9 +173,9 @@ EXPORT_SYMBOL(drm_property_create_enum);
|
||||
* @supported_bits: bitmask of all supported enumeration values
|
||||
*
|
||||
* This creates a new bitmask drm property which can then be attached to a drm
|
||||
* object with drm_object_attach_property. The returned property object must be
|
||||
* freed with drm_property_destroy(), which is done automatically when calling
|
||||
* drm_mode_config_cleanup().
|
||||
* object with drm_object_attach_property(). The returned property object must
|
||||
* be freed with drm_property_destroy(), which is done automatically when
|
||||
* calling drm_mode_config_cleanup().
|
||||
*
|
||||
* Compared to plain enumeration properties userspace is allowed to set any
|
||||
* or'ed together combination of the predefined property bitflag values
|
||||
@ -245,9 +245,9 @@ static struct drm_property *property_create_range(struct drm_device *dev,
|
||||
* @max: maximum value of the property
|
||||
*
|
||||
* This creates a new generic drm property which can then be attached to a drm
|
||||
* object with drm_object_attach_property. The returned property object must be
|
||||
* freed with drm_property_destroy(), which is done automatically when calling
|
||||
* drm_mode_config_cleanup().
|
||||
* object with drm_object_attach_property(). The returned property object must
|
||||
* be freed with drm_property_destroy(), which is done automatically when
|
||||
* calling drm_mode_config_cleanup().
|
||||
*
|
||||
* Userspace is allowed to set any unsigned integer value in the (min, max)
|
||||
* range inclusive.
|
||||
@ -273,9 +273,9 @@ EXPORT_SYMBOL(drm_property_create_range);
|
||||
* @max: maximum value of the property
|
||||
*
|
||||
* This creates a new generic drm property which can then be attached to a drm
|
||||
* object with drm_object_attach_property. The returned property object must be
|
||||
* freed with drm_property_destroy(), which is done automatically when calling
|
||||
* drm_mode_config_cleanup().
|
||||
* object with drm_object_attach_property(). The returned property object must
|
||||
* be freed with drm_property_destroy(), which is done automatically when
|
||||
* calling drm_mode_config_cleanup().
|
||||
*
|
||||
* Userspace is allowed to set any signed integer value in the (min, max)
|
||||
* range inclusive.
|
||||
@ -300,9 +300,9 @@ EXPORT_SYMBOL(drm_property_create_signed_range);
|
||||
* @type: object type from DRM_MODE_OBJECT_* defines
|
||||
*
|
||||
* This creates a new generic drm property which can then be attached to a drm
|
||||
* object with drm_object_attach_property. The returned property object must be
|
||||
* freed with drm_property_destroy(), which is done automatically when calling
|
||||
* drm_mode_config_cleanup().
|
||||
* object with drm_object_attach_property(). The returned property object must
|
||||
* be freed with drm_property_destroy(), which is done automatically when
|
||||
* calling drm_mode_config_cleanup().
|
||||
*
|
||||
* Userspace is only allowed to set this to any property value of the given
|
||||
* @type. Only useful for atomic properties, which is enforced.
|
||||
@ -338,9 +338,9 @@ EXPORT_SYMBOL(drm_property_create_object);
|
||||
* @name: name of the property
|
||||
*
|
||||
* This creates a new generic drm property which can then be attached to a drm
|
||||
* object with drm_object_attach_property. The returned property object must be
|
||||
* freed with drm_property_destroy(), which is done automatically when calling
|
||||
* drm_mode_config_cleanup().
|
||||
* object with drm_object_attach_property(). The returned property object must
|
||||
* be freed with drm_property_destroy(), which is done automatically when
|
||||
* calling drm_mode_config_cleanup().
|
||||
*
|
||||
* This is implemented as a ranged property with only {0, 1} as valid values.
|
||||
*
|
||||
@ -729,7 +729,6 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
|
||||
struct drm_mode_get_blob *out_resp = data;
|
||||
struct drm_property_blob *blob;
|
||||
int ret = 0;
|
||||
void __user *blob_ptr;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return -EINVAL;
|
||||
@ -739,8 +738,9 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
|
||||
return -ENOENT;
|
||||
|
||||
if (out_resp->length == blob->length) {
|
||||
blob_ptr = (void __user *)(unsigned long)out_resp->data;
|
||||
if (copy_to_user(blob_ptr, blob->data, blob->length)) {
|
||||
if (copy_to_user(u64_to_user_ptr(out_resp->data),
|
||||
blob->data,
|
||||
blob->length)) {
|
||||
ret = -EFAULT;
|
||||
goto unref;
|
||||
}
|
||||
@ -757,7 +757,6 @@ int drm_mode_createblob_ioctl(struct drm_device *dev,
|
||||
{
|
||||
struct drm_mode_create_blob *out_resp = data;
|
||||
struct drm_property_blob *blob;
|
||||
void __user *blob_ptr;
|
||||
int ret = 0;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
@ -767,8 +766,9 @@ int drm_mode_createblob_ioctl(struct drm_device *dev,
|
||||
if (IS_ERR(blob))
|
||||
return PTR_ERR(blob);
|
||||
|
||||
blob_ptr = (void __user *)(unsigned long)out_resp->data;
|
||||
if (copy_from_user(blob->data, blob_ptr, out_resp->length)) {
|
||||
if (copy_from_user(blob->data,
|
||||
u64_to_user_ptr(out_resp->data),
|
||||
out_resp->length)) {
|
||||
ret = -EFAULT;
|
||||
goto out_blob;
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ static struct drm_driver hibmc_driver = {
|
||||
.irq_handler = hibmc_drm_interrupt,
|
||||
};
|
||||
|
||||
static int hibmc_pm_suspend(struct device *dev)
|
||||
static int __maybe_unused hibmc_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct drm_device *drm_dev = pci_get_drvdata(pdev);
|
||||
@ -112,7 +112,7 @@ static int hibmc_pm_suspend(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hibmc_pm_resume(struct device *dev)
|
||||
static int __maybe_unused hibmc_pm_resume(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct drm_device *drm_dev = pci_get_drvdata(pdev);
|
||||
@ -377,9 +377,9 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
|
||||
int ret;
|
||||
|
||||
dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
|
||||
if (!dev) {
|
||||
if (IS_ERR(dev)) {
|
||||
DRM_ERROR("failed to allocate drm_device\n");
|
||||
return -ENOMEM;
|
||||
return PTR_ERR(dev);
|
||||
}
|
||||
|
||||
dev->pdev = pdev;
|
||||
|
@ -1896,7 +1896,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
|
||||
fbdev_fb->base.height,
|
||||
fbdev_fb->base.depth,
|
||||
fbdev_fb->base.bits_per_pixel,
|
||||
fbdev_fb->base.modifier[0],
|
||||
fbdev_fb->base.modifier,
|
||||
drm_framebuffer_read_refcount(&fbdev_fb->base));
|
||||
describe_obj(m, fbdev_fb->obj);
|
||||
seq_putc(m, '\n');
|
||||
@ -1914,7 +1914,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
|
||||
fb->base.height,
|
||||
fb->base.depth,
|
||||
fb->base.bits_per_pixel,
|
||||
fb->base.modifier[0],
|
||||
fb->base.modifier,
|
||||
drm_framebuffer_read_refcount(&fb->base));
|
||||
describe_obj(m, fb->obj);
|
||||
seq_putc(m, '\n');
|
||||
|
@ -144,8 +144,8 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
|
||||
if (state->fb && drm_rotation_90_or_270(state->rotation)) {
|
||||
struct drm_format_name_buf format_name;
|
||||
|
||||
if (!(state->fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
|
||||
state->fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) {
|
||||
if (state->fb->modifier != I915_FORMAT_MOD_Y_TILED &&
|
||||
state->fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
|
||||
DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -2189,7 +2189,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
|
||||
|
||||
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
|
||||
|
||||
alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
|
||||
alignment = intel_surf_alignment(dev_priv, fb->modifier);
|
||||
|
||||
intel_fill_fb_ggtt_view(&view, fb, rotation);
|
||||
|
||||
@ -2350,13 +2350,13 @@ static u32 intel_adjust_tile_offset(int *x, int *y,
|
||||
|
||||
WARN_ON(new_offset > old_offset);
|
||||
|
||||
if (fb->modifier[plane] != DRM_FORMAT_MOD_NONE) {
|
||||
if (fb->modifier != DRM_FORMAT_MOD_NONE) {
|
||||
unsigned int tile_size, tile_width, tile_height;
|
||||
unsigned int pitch_tiles;
|
||||
|
||||
tile_size = intel_tile_size(dev_priv);
|
||||
intel_tile_dims(dev_priv, &tile_width, &tile_height,
|
||||
fb->modifier[plane], cpp);
|
||||
fb->modifier, cpp);
|
||||
|
||||
if (drm_rotation_90_or_270(rotation)) {
|
||||
pitch_tiles = pitch / tile_height;
|
||||
@ -2399,7 +2399,7 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv,
|
||||
unsigned int rotation,
|
||||
u32 alignment)
|
||||
{
|
||||
uint64_t fb_modifier = fb->modifier[plane];
|
||||
uint64_t fb_modifier = fb->modifier;
|
||||
unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
|
||||
u32 offset, offset_aligned;
|
||||
|
||||
@ -2458,7 +2458,7 @@ u32 intel_compute_tile_offset(int *x, int *y,
|
||||
if (fb->pixel_format == DRM_FORMAT_NV12 && plane == 1)
|
||||
alignment = 4096;
|
||||
else
|
||||
alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
|
||||
alignment = intel_surf_alignment(dev_priv, fb->modifier);
|
||||
|
||||
return _intel_compute_tile_offset(dev_priv, x, y, fb, plane, pitch,
|
||||
rotation, alignment);
|
||||
@ -2540,13 +2540,13 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
|
||||
DRM_ROTATE_0, tile_size);
|
||||
offset /= tile_size;
|
||||
|
||||
if (fb->modifier[i] != DRM_FORMAT_MOD_NONE) {
|
||||
if (fb->modifier != DRM_FORMAT_MOD_NONE) {
|
||||
unsigned int tile_width, tile_height;
|
||||
unsigned int pitch_tiles;
|
||||
struct drm_rect r;
|
||||
|
||||
intel_tile_dims(dev_priv, &tile_width, &tile_height,
|
||||
fb->modifier[i], cpp);
|
||||
fb->modifier, cpp);
|
||||
|
||||
rot_info->plane[i].offset = offset;
|
||||
rot_info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], tile_width * cpp);
|
||||
@ -2705,7 +2705,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
|
||||
mode_cmd.width = fb->width;
|
||||
mode_cmd.height = fb->height;
|
||||
mode_cmd.pitches[0] = fb->pitches[0];
|
||||
mode_cmd.modifier[0] = fb->modifier[0];
|
||||
mode_cmd.modifier[0] = fb->modifier;
|
||||
mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
|
||||
|
||||
if (intel_framebuffer_init(dev, to_intel_framebuffer(fb),
|
||||
@ -2835,7 +2835,7 @@ static int skl_max_plane_width(const struct drm_framebuffer *fb, int plane,
|
||||
{
|
||||
int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
|
||||
|
||||
switch (fb->modifier[plane]) {
|
||||
switch (fb->modifier) {
|
||||
case DRM_FORMAT_MOD_NONE:
|
||||
case I915_FORMAT_MOD_X_TILED:
|
||||
switch (cpp) {
|
||||
@ -2866,7 +2866,7 @@ static int skl_max_plane_width(const struct drm_framebuffer *fb, int plane,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(fb->modifier[plane]);
|
||||
MISSING_CASE(fb->modifier);
|
||||
}
|
||||
|
||||
return 2048;
|
||||
@ -2894,7 +2894,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
|
||||
intel_add_fb_offsets(&x, &y, plane_state, 0);
|
||||
offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
|
||||
|
||||
alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
|
||||
alignment = intel_surf_alignment(dev_priv, fb->modifier);
|
||||
|
||||
/*
|
||||
* AUX surface offset is specified as the distance from the
|
||||
@ -2911,7 +2911,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
|
||||
*
|
||||
* TODO: linear and Y-tiled seem fine, Yf untested,
|
||||
*/
|
||||
if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) {
|
||||
if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
|
||||
int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
|
||||
|
||||
while ((x + w) * cpp > fb->pitches[0]) {
|
||||
@ -3059,7 +3059,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
|
||||
}
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 4 &&
|
||||
fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
|
||||
fb->modifier == I915_FORMAT_MOD_X_TILED)
|
||||
dspcntr |= DISPPLANE_TILED;
|
||||
|
||||
if (rotation & DRM_ROTATE_180)
|
||||
@ -3170,7 +3170,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
|
||||
if (fb->modifier == I915_FORMAT_MOD_X_TILED)
|
||||
dspcntr |= DISPPLANE_TILED;
|
||||
|
||||
if (rotation & DRM_ROTATE_180)
|
||||
@ -3280,9 +3280,9 @@ u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane,
|
||||
if (drm_rotation_90_or_270(rotation)) {
|
||||
int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
|
||||
|
||||
stride /= intel_tile_height(dev_priv, fb->modifier[0], cpp);
|
||||
stride /= intel_tile_height(dev_priv, fb->modifier, cpp);
|
||||
} else {
|
||||
stride /= intel_fb_stride_alignment(dev_priv, fb->modifier[0],
|
||||
stride /= intel_fb_stride_alignment(dev_priv, fb->modifier,
|
||||
fb->pixel_format);
|
||||
}
|
||||
|
||||
@ -3398,7 +3398,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
|
||||
PLANE_CTL_PIPE_CSC_ENABLE;
|
||||
|
||||
plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
|
||||
plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
|
||||
plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
|
||||
plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
|
||||
plane_ctl |= skl_plane_ctl_rotation(rotation);
|
||||
|
||||
@ -8707,7 +8707,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
|
||||
if (INTEL_GEN(dev_priv) >= 4) {
|
||||
if (val & DISPPLANE_TILED) {
|
||||
plane_config->tiling = I915_TILING_X;
|
||||
fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
|
||||
fb->modifier = I915_FORMAT_MOD_X_TILED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8736,7 +8736,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
|
||||
|
||||
aligned_height = intel_fb_align_height(dev, fb->height,
|
||||
fb->pixel_format,
|
||||
fb->modifier[0]);
|
||||
fb->modifier);
|
||||
|
||||
plane_config->size = fb->pitches[0] * aligned_height;
|
||||
|
||||
@ -9748,17 +9748,17 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
|
||||
tiling = val & PLANE_CTL_TILED_MASK;
|
||||
switch (tiling) {
|
||||
case PLANE_CTL_TILED_LINEAR:
|
||||
fb->modifier[0] = DRM_FORMAT_MOD_NONE;
|
||||
fb->modifier = DRM_FORMAT_MOD_NONE;
|
||||
break;
|
||||
case PLANE_CTL_TILED_X:
|
||||
plane_config->tiling = I915_TILING_X;
|
||||
fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
|
||||
fb->modifier = I915_FORMAT_MOD_X_TILED;
|
||||
break;
|
||||
case PLANE_CTL_TILED_Y:
|
||||
fb->modifier[0] = I915_FORMAT_MOD_Y_TILED;
|
||||
fb->modifier = I915_FORMAT_MOD_Y_TILED;
|
||||
break;
|
||||
case PLANE_CTL_TILED_YF:
|
||||
fb->modifier[0] = I915_FORMAT_MOD_Yf_TILED;
|
||||
fb->modifier = I915_FORMAT_MOD_Yf_TILED;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(tiling);
|
||||
@ -9775,13 +9775,13 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
|
||||
fb->width = ((val >> 0) & 0x1fff) + 1;
|
||||
|
||||
val = I915_READ(PLANE_STRIDE(pipe, 0));
|
||||
stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
|
||||
stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier,
|
||||
fb->pixel_format);
|
||||
fb->pitches[0] = (val & 0x3ff) * stride_mult;
|
||||
|
||||
aligned_height = intel_fb_align_height(dev, fb->height,
|
||||
fb->pixel_format,
|
||||
fb->modifier[0]);
|
||||
fb->modifier);
|
||||
|
||||
plane_config->size = fb->pitches[0] * aligned_height;
|
||||
|
||||
@ -9849,7 +9849,7 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
|
||||
if (INTEL_GEN(dev_priv) >= 4) {
|
||||
if (val & DISPPLANE_TILED) {
|
||||
plane_config->tiling = I915_TILING_X;
|
||||
fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
|
||||
fb->modifier = I915_FORMAT_MOD_X_TILED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -9878,7 +9878,7 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
|
||||
|
||||
aligned_height = intel_fb_align_height(dev, fb->height,
|
||||
fb->pixel_format,
|
||||
fb->modifier[0]);
|
||||
fb->modifier);
|
||||
|
||||
plane_config->size = fb->pitches[0] * aligned_height;
|
||||
|
||||
@ -11784,7 +11784,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
|
||||
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
||||
intel_ring_emit(ring, fb->pitches[0]);
|
||||
intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset |
|
||||
intel_fb_modifier_to_tiling(fb->modifier[0]));
|
||||
intel_fb_modifier_to_tiling(fb->modifier));
|
||||
|
||||
/* XXX Enabling the panel-fitter across page-flip is so far
|
||||
* untested on non-native modes, so ignore it for now.
|
||||
@ -11817,7 +11817,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
|
||||
intel_ring_emit(ring, MI_DISPLAY_FLIP |
|
||||
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
||||
intel_ring_emit(ring, fb->pitches[0] |
|
||||
intel_fb_modifier_to_tiling(fb->modifier[0]));
|
||||
intel_fb_modifier_to_tiling(fb->modifier));
|
||||
intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset);
|
||||
|
||||
/* Contrary to the suggestions in the documentation,
|
||||
@ -11923,7 +11923,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
|
||||
|
||||
intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
|
||||
intel_ring_emit(ring, fb->pitches[0] |
|
||||
intel_fb_modifier_to_tiling(fb->modifier[0]));
|
||||
intel_fb_modifier_to_tiling(fb->modifier));
|
||||
intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset);
|
||||
intel_ring_emit(ring, (MI_NOOP));
|
||||
|
||||
@ -11969,7 +11969,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
|
||||
|
||||
ctl = I915_READ(PLANE_CTL(pipe, 0));
|
||||
ctl &= ~PLANE_CTL_TILED_MASK;
|
||||
switch (fb->modifier[0]) {
|
||||
switch (fb->modifier) {
|
||||
case DRM_FORMAT_MOD_NONE:
|
||||
break;
|
||||
case I915_FORMAT_MOD_X_TILED:
|
||||
@ -11982,7 +11982,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
|
||||
ctl |= PLANE_CTL_TILED_YF;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(fb->modifier[0]);
|
||||
MISSING_CASE(fb->modifier);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -12007,7 +12007,7 @@ static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc,
|
||||
|
||||
dspcntr = I915_READ(reg);
|
||||
|
||||
if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
|
||||
if (fb->modifier == I915_FORMAT_MOD_X_TILED)
|
||||
dspcntr |= DISPPLANE_TILED;
|
||||
else
|
||||
dspcntr &= ~DISPPLANE_TILED;
|
||||
@ -12223,7 +12223,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
||||
engine = dev_priv->engine[BCS];
|
||||
if (fb->modifier[0] != old_fb->modifier[0])
|
||||
if (fb->modifier != old_fb->modifier)
|
||||
/* vlv: DISPLAY_FLIP fails to change tiling */
|
||||
engine = NULL;
|
||||
} else if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)) {
|
||||
@ -12379,7 +12379,7 @@ static bool intel_wm_need_update(struct drm_plane *plane,
|
||||
if (!cur->base.fb || !new->base.fb)
|
||||
return false;
|
||||
|
||||
if (cur->base.fb->modifier[0] != new->base.fb->modifier[0] ||
|
||||
if (cur->base.fb->modifier != new->base.fb->modifier ||
|
||||
cur->base.rotation != new->base.rotation ||
|
||||
drm_rect_width(&new->base.src) != drm_rect_width(&cur->base.src) ||
|
||||
drm_rect_height(&new->base.src) != drm_rect_height(&cur->base.src) ||
|
||||
@ -15106,7 +15106,7 @@ intel_check_cursor_plane(struct drm_plane *plane,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (fb->modifier[0] != DRM_FORMAT_MOD_NONE) {
|
||||
if (fb->modifier != DRM_FORMAT_MOD_NONE) {
|
||||
DRM_DEBUG_KMS("cursor cannot be tiled\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -633,7 +633,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
|
||||
cur_size = intel_crtc->config->base.adjusted_mode.crtc_vdisplay;
|
||||
cur_size = intel_fb_align_height(dev, cur_size,
|
||||
fb->base.pixel_format,
|
||||
fb->base.modifier[0]);
|
||||
fb->base.modifier);
|
||||
cur_size *= fb->base.pitches[0];
|
||||
DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n",
|
||||
pipe_name(intel_crtc->pipe),
|
||||
|
@ -3067,7 +3067,7 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state)
|
||||
latency = dev_priv->wm.skl_latency[level];
|
||||
|
||||
if (skl_needs_memory_bw_wa(intel_state) &&
|
||||
plane->base.state->fb->modifier[0] ==
|
||||
plane->base.state->fb->modifier ==
|
||||
I915_FORMAT_MOD_X_TILED)
|
||||
latency += 15;
|
||||
|
||||
@ -3327,8 +3327,8 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate,
|
||||
return 0;
|
||||
|
||||
/* For Non Y-tile return 8-blocks */
|
||||
if (fb->modifier[0] != I915_FORMAT_MOD_Y_TILED &&
|
||||
fb->modifier[0] != I915_FORMAT_MOD_Yf_TILED)
|
||||
if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
|
||||
fb->modifier != I915_FORMAT_MOD_Yf_TILED)
|
||||
return 8;
|
||||
|
||||
src_w = drm_rect_width(&intel_pstate->base.src) >> 16;
|
||||
@ -3597,7 +3597,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (apply_memory_bw_wa && fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
|
||||
if (apply_memory_bw_wa && fb->modifier == I915_FORMAT_MOD_X_TILED)
|
||||
latency += 15;
|
||||
|
||||
width = drm_rect_width(&intel_pstate->base.src) >> 16;
|
||||
@ -3636,12 +3636,12 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
|
||||
y_min_scanlines *= 2;
|
||||
|
||||
plane_bytes_per_line = width * cpp;
|
||||
if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
|
||||
fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) {
|
||||
if (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
|
||||
fb->modifier == I915_FORMAT_MOD_Yf_TILED) {
|
||||
plane_blocks_per_line =
|
||||
DIV_ROUND_UP(plane_bytes_per_line * y_min_scanlines, 512);
|
||||
plane_blocks_per_line /= y_min_scanlines;
|
||||
} else if (fb->modifier[0] == DRM_FORMAT_MOD_NONE) {
|
||||
} else if (fb->modifier == DRM_FORMAT_MOD_NONE) {
|
||||
plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512)
|
||||
+ 1;
|
||||
} else {
|
||||
@ -3656,8 +3656,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
|
||||
|
||||
y_tile_minimum = plane_blocks_per_line * y_min_scanlines;
|
||||
|
||||
if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
|
||||
fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) {
|
||||
if (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
|
||||
fb->modifier == I915_FORMAT_MOD_Yf_TILED) {
|
||||
selected_result = max(method2, y_tile_minimum);
|
||||
} else {
|
||||
if ((cpp * cstate->base.adjusted_mode.crtc_htotal / 512 < 1) &&
|
||||
@ -3673,8 +3673,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
|
||||
res_lines = DIV_ROUND_UP(selected_result, plane_blocks_per_line);
|
||||
|
||||
if (level >= 1 && level <= 7) {
|
||||
if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
|
||||
fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) {
|
||||
if (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
|
||||
fb->modifier == I915_FORMAT_MOD_Yf_TILED) {
|
||||
res_blocks += y_tile_minimum;
|
||||
res_lines += y_min_scanlines;
|
||||
} else {
|
||||
|
@ -224,7 +224,7 @@ skl_update_plane(struct drm_plane *drm_plane,
|
||||
PLANE_CTL_PIPE_CSC_ENABLE;
|
||||
|
||||
plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
|
||||
plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
|
||||
plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
|
||||
|
||||
plane_ctl |= skl_plane_ctl_rotation(rotation);
|
||||
|
||||
@ -406,7 +406,7 @@ vlv_update_plane(struct drm_plane *dplane,
|
||||
*/
|
||||
sprctl |= SP_GAMMA_ENABLE;
|
||||
|
||||
if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
|
||||
if (fb->modifier == I915_FORMAT_MOD_X_TILED)
|
||||
sprctl |= SP_TILED;
|
||||
|
||||
if (rotation & DRM_ROTATE_180)
|
||||
@ -448,7 +448,7 @@ vlv_update_plane(struct drm_plane *dplane,
|
||||
I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
|
||||
I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
|
||||
|
||||
if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
|
||||
if (fb->modifier == I915_FORMAT_MOD_X_TILED)
|
||||
I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
|
||||
else
|
||||
I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
|
||||
@ -531,7 +531,7 @@ ivb_update_plane(struct drm_plane *plane,
|
||||
*/
|
||||
sprctl |= SPRITE_GAMMA_ENABLE;
|
||||
|
||||
if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
|
||||
if (fb->modifier == I915_FORMAT_MOD_X_TILED)
|
||||
sprctl |= SPRITE_TILED;
|
||||
|
||||
if (rotation & DRM_ROTATE_180)
|
||||
@ -584,7 +584,7 @@ ivb_update_plane(struct drm_plane *plane,
|
||||
* register */
|
||||
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
||||
I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
|
||||
else if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
|
||||
else if (fb->modifier == I915_FORMAT_MOD_X_TILED)
|
||||
I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
|
||||
else
|
||||
I915_WRITE(SPRLINOFF(pipe), linear_offset);
|
||||
@ -669,7 +669,7 @@ ilk_update_plane(struct drm_plane *plane,
|
||||
*/
|
||||
dvscntr |= DVS_GAMMA_ENABLE;
|
||||
|
||||
if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
|
||||
if (fb->modifier == I915_FORMAT_MOD_X_TILED)
|
||||
dvscntr |= DVS_TILED;
|
||||
|
||||
if (rotation & DRM_ROTATE_180)
|
||||
@ -712,7 +712,7 @@ ilk_update_plane(struct drm_plane *plane,
|
||||
I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
|
||||
I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
|
||||
|
||||
if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
|
||||
if (fb->modifier == I915_FORMAT_MOD_X_TILED)
|
||||
I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
|
||||
else
|
||||
I915_WRITE(DVSLINOFF(pipe), linear_offset);
|
||||
|
@ -40,7 +40,7 @@ enum mdp4_frame_format mdp4_get_frame_format(struct drm_framebuffer *fb)
|
||||
{
|
||||
bool is_tile = false;
|
||||
|
||||
if (fb->modifier[1] == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
|
||||
if (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
|
||||
is_tile = true;
|
||||
|
||||
if (fb->pixel_format == DRM_FORMAT_NV12 && is_tile)
|
||||
|
@ -31,6 +31,10 @@
|
||||
|
||||
#define pr_fmt(fmt) "vgaarb: " fmt
|
||||
|
||||
#define vgaarb_dbg(dev, fmt, arg...) dev_dbg(dev, "vgaarb: " fmt, ##arg)
|
||||
#define vgaarb_info(dev, fmt, arg...) dev_info(dev, "vgaarb: " fmt, ##arg)
|
||||
#define vgaarb_err(dev, fmt, arg...) dev_err(dev, "vgaarb: " fmt, ##arg)
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
@ -188,6 +192,7 @@ static void vga_check_first_use(void)
|
||||
static struct vga_device *__vga_tryget(struct vga_device *vgadev,
|
||||
unsigned int rsrc)
|
||||
{
|
||||
struct device *dev = &vgadev->pdev->dev;
|
||||
unsigned int wants, legacy_wants, match;
|
||||
struct vga_device *conflict;
|
||||
unsigned int pci_bits;
|
||||
@ -203,8 +208,8 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
|
||||
(vgadev->decodes & VGA_RSRC_LEGACY_MEM))
|
||||
rsrc |= VGA_RSRC_LEGACY_MEM;
|
||||
|
||||
pr_debug("%s: %d\n", __func__, rsrc);
|
||||
pr_debug("%s: owns: %d\n", __func__, vgadev->owns);
|
||||
vgaarb_dbg(dev, "%s: %d\n", __func__, rsrc);
|
||||
vgaarb_dbg(dev, "%s: owns: %d\n", __func__, vgadev->owns);
|
||||
|
||||
/* Check what resources we need to acquire */
|
||||
wants = rsrc & ~vgadev->owns;
|
||||
@ -336,9 +341,10 @@ lock_them:
|
||||
|
||||
static void __vga_put(struct vga_device *vgadev, unsigned int rsrc)
|
||||
{
|
||||
struct device *dev = &vgadev->pdev->dev;
|
||||
unsigned int old_locks = vgadev->locks;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
vgaarb_dbg(dev, "%s\n", __func__);
|
||||
|
||||
/* Update our counters, and account for equivalent legacy resources
|
||||
* if we decode them
|
||||
@ -611,7 +617,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
|
||||
/* Allocate structure */
|
||||
vgadev = kzalloc(sizeof(struct vga_device), GFP_KERNEL);
|
||||
if (vgadev == NULL) {
|
||||
pr_err("failed to allocate pci device\n");
|
||||
vgaarb_err(&pdev->dev, "failed to allocate VGA arbiter data\n");
|
||||
/*
|
||||
* What to do on allocation failure ? For now, let's just do
|
||||
* nothing, I'm not sure there is anything saner to be done.
|
||||
@ -663,7 +669,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
|
||||
*/
|
||||
if (vga_default == NULL &&
|
||||
((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) {
|
||||
pr_info("setting as boot device: PCI:%s\n", pci_name(pdev));
|
||||
vgaarb_info(&pdev->dev, "setting as boot VGA device\n");
|
||||
vga_set_default_device(pdev);
|
||||
}
|
||||
|
||||
@ -672,8 +678,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
|
||||
/* Add to the list */
|
||||
list_add(&vgadev->list, &vga_list);
|
||||
vga_count++;
|
||||
pr_info("device added: PCI:%s,decodes=%s,owns=%s,locks=%s\n",
|
||||
pci_name(pdev),
|
||||
vgaarb_info(&pdev->dev, "VGA device added: decodes=%s,owns=%s,locks=%s\n",
|
||||
vga_iostate_to_str(vgadev->decodes),
|
||||
vga_iostate_to_str(vgadev->owns),
|
||||
vga_iostate_to_str(vgadev->locks));
|
||||
@ -725,6 +730,7 @@ bail:
|
||||
static inline void vga_update_device_decodes(struct vga_device *vgadev,
|
||||
int new_decodes)
|
||||
{
|
||||
struct device *dev = &vgadev->pdev->dev;
|
||||
int old_decodes, decodes_removed, decodes_unlocked;
|
||||
|
||||
old_decodes = vgadev->decodes;
|
||||
@ -732,8 +738,7 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
|
||||
decodes_unlocked = vgadev->locks & decodes_removed;
|
||||
vgadev->decodes = new_decodes;
|
||||
|
||||
pr_info("device changed decodes: PCI:%s,olddecodes=%s,decodes=%s:owns=%s\n",
|
||||
pci_name(vgadev->pdev),
|
||||
vgaarb_info(dev, "changed VGA decodes: olddecodes=%s,decodes=%s:owns=%s\n",
|
||||
vga_iostate_to_str(old_decodes),
|
||||
vga_iostate_to_str(vgadev->decodes),
|
||||
vga_iostate_to_str(vgadev->owns));
|
||||
@ -754,7 +759,7 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
|
||||
if (!(old_decodes & VGA_RSRC_LEGACY_MASK) &&
|
||||
new_decodes & VGA_RSRC_LEGACY_MASK)
|
||||
vga_decode_count++;
|
||||
pr_debug("decoding count now is: %d\n", vga_decode_count);
|
||||
vgaarb_dbg(dev, "decoding count now is: %d\n", vga_decode_count);
|
||||
}
|
||||
|
||||
static void __vga_set_legacy_decoding(struct pci_dev *pdev,
|
||||
@ -1184,24 +1189,25 @@ static ssize_t vga_arb_write(struct file *file, const char __user *buf,
|
||||
ret_val = -EPROTO;
|
||||
goto done;
|
||||
}
|
||||
pr_debug("%s ==> %x:%x:%x.%x\n", curr_pos,
|
||||
domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
|
||||
|
||||
pdev = pci_get_domain_bus_and_slot(domain, bus, devfn);
|
||||
pr_debug("pdev %p\n", pdev);
|
||||
if (!pdev) {
|
||||
pr_err("invalid PCI address %x:%x:%x\n",
|
||||
domain, bus, devfn);
|
||||
pr_debug("invalid PCI address %04x:%02x:%02x.%x\n",
|
||||
domain, bus, PCI_SLOT(devfn),
|
||||
PCI_FUNC(devfn));
|
||||
ret_val = -ENODEV;
|
||||
goto done;
|
||||
}
|
||||
|
||||
pr_debug("%s ==> %04x:%02x:%02x.%x pdev %p\n", curr_pos,
|
||||
domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
||||
pdev);
|
||||
}
|
||||
|
||||
vgadev = vgadev_find(pdev);
|
||||
pr_debug("vgadev %p\n", vgadev);
|
||||
if (vgadev == NULL) {
|
||||
if (pdev) {
|
||||
pr_err("this pci device is not a vga device\n");
|
||||
vgaarb_dbg(&pdev->dev, "not a VGA device\n");
|
||||
pci_dev_put(pdev);
|
||||
}
|
||||
|
||||
@ -1221,7 +1227,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user *buf,
|
||||
}
|
||||
}
|
||||
if (i == MAX_USER_CARDS) {
|
||||
pr_err("maximum user cards (%d) number reached!\n",
|
||||
vgaarb_dbg(&pdev->dev, "maximum user cards (%d) number reached, ignoring this one!\n",
|
||||
MAX_USER_CARDS);
|
||||
pci_dev_put(pdev);
|
||||
/* XXX: which value to return? */
|
||||
@ -1310,8 +1316,8 @@ static int vga_arb_release(struct inode *inode, struct file *file)
|
||||
uc = &priv->cards[i];
|
||||
if (uc->pdev == NULL)
|
||||
continue;
|
||||
pr_debug("uc->io_cnt == %d, uc->mem_cnt == %d\n",
|
||||
uc->io_cnt, uc->mem_cnt);
|
||||
vgaarb_dbg(&uc->pdev->dev, "uc->io_cnt == %d, uc->mem_cnt == %d\n",
|
||||
uc->io_cnt, uc->mem_cnt);
|
||||
while (uc->io_cnt--)
|
||||
vga_put(uc->pdev, VGA_RSRC_LEGACY_IO);
|
||||
while (uc->mem_cnt--)
|
||||
@ -1364,7 +1370,7 @@ static int pci_notify(struct notifier_block *nb, unsigned long action,
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
bool notify = false;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
vgaarb_dbg(dev, "%s\n", __func__);
|
||||
|
||||
/* For now we're only intereted in devices added and removed. I didn't
|
||||
* test this thing here, so someone needs to double check for the
|
||||
@ -1416,9 +1422,8 @@ static int __init vga_arb_device_init(void)
|
||||
PCI_ANY_ID, pdev)) != NULL)
|
||||
vga_arbiter_add_pci_device(pdev);
|
||||
|
||||
pr_info("loaded\n");
|
||||
|
||||
list_for_each_entry(vgadev, &vga_list, list) {
|
||||
struct device *dev = &vgadev->pdev->dev;
|
||||
#if defined(CONFIG_X86) || defined(CONFIG_IA64)
|
||||
/*
|
||||
* Override vga_arbiter_add_pci_device()'s I/O based detection
|
||||
@ -1451,21 +1456,19 @@ static int __init vga_arb_device_init(void)
|
||||
continue;
|
||||
|
||||
if (!vga_default_device())
|
||||
pr_info("setting as boot device: PCI:%s\n",
|
||||
pci_name(vgadev->pdev));
|
||||
vgaarb_info(dev, "setting as boot device\n");
|
||||
else if (vgadev->pdev != vga_default_device())
|
||||
pr_info("overriding boot device: PCI:%s\n",
|
||||
pci_name(vgadev->pdev));
|
||||
vgaarb_info(dev, "overriding boot device\n");
|
||||
vga_set_default_device(vgadev->pdev);
|
||||
}
|
||||
#endif
|
||||
if (vgadev->bridge_has_one_vga)
|
||||
pr_info("bridge control possible %s\n",
|
||||
pci_name(vgadev->pdev));
|
||||
vgaarb_info(dev, "bridge control possible\n");
|
||||
else
|
||||
pr_info("no bridge control possible %s\n",
|
||||
pci_name(vgadev->pdev));
|
||||
vgaarb_info(dev, "no bridge control possible\n");
|
||||
}
|
||||
|
||||
pr_info("loaded\n");
|
||||
return rc;
|
||||
}
|
||||
subsys_initcall(vga_arb_device_init);
|
||||
|
@ -372,6 +372,7 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct drm_minor;
|
||||
int drm_atomic_debugfs_init(struct drm_minor *minor);
|
||||
int drm_atomic_debugfs_cleanup(struct drm_minor *minor);
|
||||
#endif
|
||||
|
||||
#define for_each_connector_in_state(__state, connector, connector_state, __i) \
|
||||
@ -417,7 +418,7 @@ int drm_atomic_debugfs_init(struct drm_minor *minor);
|
||||
* should clear mode_changed during its ->atomic_check.
|
||||
*/
|
||||
static inline bool
|
||||
drm_atomic_crtc_needs_modeset(struct drm_crtc_state *state)
|
||||
drm_atomic_crtc_needs_modeset(const struct drm_crtc_state *state)
|
||||
{
|
||||
return state->mode_changed || state->active_changed ||
|
||||
state->connectors_changed;
|
||||
|
@ -291,6 +291,8 @@ struct drm_driver {
|
||||
void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
|
||||
|
||||
/**
|
||||
* @gem_create_object: constructor for gem objects
|
||||
*
|
||||
* Hook for allocating the GEM object struct, for use by core
|
||||
* helpers.
|
||||
*/
|
||||
|
@ -149,12 +149,12 @@ struct drm_framebuffer {
|
||||
*/
|
||||
unsigned int offsets[4];
|
||||
/**
|
||||
* @modifier: Data layout modifier, per buffer. This is used to describe
|
||||
* @modifier: Data layout modifier. This is used to describe
|
||||
* tiling, or also special layouts (like compression) of auxiliary
|
||||
* buffers. For userspace created object this is copied from
|
||||
* drm_mode_fb_cmd2.
|
||||
*/
|
||||
uint64_t modifier[4];
|
||||
uint64_t modifier;
|
||||
/**
|
||||
* @width: Logical width of the visible area of the framebuffer, in
|
||||
* pixels.
|
||||
@ -251,6 +251,24 @@ static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_framebuffer_assign - store a reference to the fb
|
||||
* @p: location to store framebuffer
|
||||
* @fb: new framebuffer (maybe NULL)
|
||||
*
|
||||
* This functions sets the location to store a reference to the framebuffer,
|
||||
* unreferencing the framebuffer that was previously stored in that location.
|
||||
*/
|
||||
static inline void drm_framebuffer_assign(struct drm_framebuffer **p,
|
||||
struct drm_framebuffer *fb)
|
||||
{
|
||||
if (fb)
|
||||
drm_framebuffer_reference(fb);
|
||||
if (*p)
|
||||
drm_framebuffer_unreference(*p);
|
||||
*p = fb;
|
||||
}
|
||||
|
||||
/*
|
||||
* drm_for_each_fb - iterate over all framebuffers
|
||||
* @fb: the loop cursor
|
||||
* @dev: the DRM device
|
||||
|
@ -308,10 +308,26 @@ void drm_mm_takedown(struct drm_mm *mm);
|
||||
bool drm_mm_clean(struct drm_mm *mm);
|
||||
|
||||
struct drm_mm_node *
|
||||
drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last);
|
||||
__drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last);
|
||||
|
||||
struct drm_mm_node *
|
||||
drm_mm_interval_next(struct drm_mm_node *node, u64 start, u64 last);
|
||||
/**
|
||||
* drm_mm_for_each_node_in_range - iterator to walk over a range of
|
||||
* allocated nodes
|
||||
* @node__: drm_mm_node structure to assign to in each iteration step
|
||||
* @mm__: drm_mm allocator to walk
|
||||
* @start__: starting offset, the first node will overlap this
|
||||
* @end__: ending offset, the last node will start before this (but may overlap)
|
||||
*
|
||||
* This iterator walks over all nodes in the range allocator that lie
|
||||
* between @start and @end. It is implemented similarly to list_for_each(),
|
||||
* but using the internal interval tree to accelerate the search for the
|
||||
* starting node, and so not safe against removal of elements. It assumes
|
||||
* that @end is within (or is the upper limit of) the drm_mm allocator.
|
||||
*/
|
||||
#define drm_mm_for_each_node_in_range(node__, mm__, start__, end__) \
|
||||
for (node__ = __drm_mm_interval_first((mm__), (start__), (end__)-1); \
|
||||
node__ && node__->start < (end__); \
|
||||
node__ = list_next_entry(node__, node_list))
|
||||
|
||||
void drm_mm_init_scan(struct drm_mm *mm,
|
||||
u64 size,
|
||||
|
@ -999,10 +999,14 @@ struct drm_mode_config_helper_funcs {
|
||||
* to implement blocking and nonblocking commits easily. It is not used
|
||||
* by the atomic helpers
|
||||
*
|
||||
* This hook should first commit the given atomic state to the hardware.
|
||||
* But drivers can add more waiting calls at the start of their
|
||||
* implementation, e.g. to wait for driver-internal request for implicit
|
||||
* syncing, before starting to commit the update to the hardware.
|
||||
* This function is called when the new atomic state has already been
|
||||
* swapped into the various state pointers. The passed in state
|
||||
* therefore contains copies of the old/previous state. This hook should
|
||||
* commit the new state into hardware. Note that the helpers have
|
||||
* already waited for preceeding atomic commits and fences, but drivers
|
||||
* can add more waiting calls at the start of their implementation, e.g.
|
||||
* to wait for driver-internal request for implicit syncing, before
|
||||
* starting to commit the update to the hardware.
|
||||
*
|
||||
* After the atomic update is committed to the hardware this hook needs
|
||||
* to call drm_atomic_helper_commit_hw_done(). Then wait for the upate
|
||||
|
@ -408,17 +408,20 @@ struct drm_mode_fb_cmd2 {
|
||||
* offsets[1]. Note that offsets[0] will generally
|
||||
* be 0 (but this is not required).
|
||||
*
|
||||
* To accommodate tiled, compressed, etc formats, a per-plane
|
||||
* To accommodate tiled, compressed, etc formats, a
|
||||
* modifier can be specified. The default value of zero
|
||||
* indicates "native" format as specified by the fourcc.
|
||||
* Vendor specific modifier token. This allows, for example,
|
||||
* different tiling/swizzling pattern on different planes.
|
||||
* See discussion above of DRM_FORMAT_MOD_xxx.
|
||||
* Vendor specific modifier token. Note that even though
|
||||
* it looks like we have a modifier per-plane, we in fact
|
||||
* do not. The modifier for each plane must be identical.
|
||||
* Thus all combinations of different data layouts for
|
||||
* multi plane formats must be enumerated as separate
|
||||
* modifiers.
|
||||
*/
|
||||
__u32 handles[4];
|
||||
__u32 pitches[4]; /* pitch for each plane */
|
||||
__u32 offsets[4]; /* offset of each plane */
|
||||
__u64 modifier[4]; /* ie, tiling, compressed (per plane) */
|
||||
__u64 modifier[4]; /* ie, tiling, compress */
|
||||
};
|
||||
|
||||
#define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01
|
||||
|
Loading…
Reference in New Issue
Block a user