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:
Dave Airlie 2016-11-30 14:28:20 +10:00
commit a90f58311f
45 changed files with 939 additions and 225 deletions

View File

@ -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
-------

View File

@ -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:

View File

@ -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
-----------------------

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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__ */

View 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;
}
}

View File

@ -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);

View File

@ -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 = {

View File

@ -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) {

View File

@ -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

View 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);

View File

@ -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 */

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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) {

View File

@ -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:

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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');

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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),

View File

@ -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 {

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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.
*/

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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