Merge tag 'topic/core-stuff-2014-11-05' of git://anongit.freedesktop.org/drm-intel into drm-next
Just various stuff all over from a bunch of people. Shortlog gives a beter overview, it's really all misc drm patches. * tag 'topic/core-stuff-2014-11-05' of git://anongit.freedesktop.org/drm-intel: drm/edid: add #defines and helpers for ELD drm/dp: Add counters in the drm_dp_aux struct for I2C NACKs and DEFERs drm: Remove compiler BUG_ON() test drm: Fix DRM_FORCE_ON_DIGITAL use drm/gma500: Don't destroy DRM properties in the driver drm/i915: Don't destroy DRM properties in the driver drm: Add a note to drm_property_create() about property lifetime gpu: drm: Fix warning caused by a parameter description in drm_crtc.c drm/dp-helper: Move the legacy helpers to gma500 drm/crtc: Remove duplicated ioctl code drm/crtc: Fix two typos gpu:drm: Fix typo in Documentation/DocBook/drm.xml gpu: drm: drm_dp_mst_topology.c: Fix improper use of strncat drm: drm_err: Remove unnecessary __func__ argument drm: Implement O_NONBLOCK support on /dev/dri/cardN
This commit is contained in:
commit
1f9e14baa9
|
@ -766,7 +766,6 @@ static void drm_mode_remove(struct drm_connector *connector,
|
|||
/**
|
||||
* drm_connector_get_cmdline_mode - reads the user's cmdline mode
|
||||
* @connector: connector to quwery
|
||||
* @mode: returned mode
|
||||
*
|
||||
* The kernel supports per-connector configration of its consoles through
|
||||
* use of the video= parameter. This function parses that option and
|
||||
|
@ -2943,7 +2942,7 @@ EXPORT_SYMBOL(drm_mode_legacy_fb_format);
|
|||
* @file_priv: drm file for the ioctl call
|
||||
*
|
||||
* Add a new FB to the specified CRTC, given a user request. This is the
|
||||
* original addfb ioclt which only supported RGB formats.
|
||||
* original addfb ioctl which only supported RGB formats.
|
||||
*
|
||||
* Called by the user via ioctl.
|
||||
*
|
||||
|
@ -2955,11 +2954,9 @@ int drm_mode_addfb(struct drm_device *dev,
|
|||
{
|
||||
struct drm_mode_fb_cmd *or = data;
|
||||
struct drm_mode_fb_cmd2 r = {};
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
struct drm_framebuffer *fb;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
/* Use new struct with format internally */
|
||||
/* convert to new format and call new ioctl */
|
||||
r.fb_id = or->fb_id;
|
||||
r.width = or->width;
|
||||
r.height = or->height;
|
||||
|
@ -2967,26 +2964,11 @@ int drm_mode_addfb(struct drm_device *dev,
|
|||
r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
|
||||
r.handles[0] = or->handle;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return -EINVAL;
|
||||
ret = drm_mode_addfb2(dev, &r, file_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((config->min_width > r.width) || (r.width > config->max_width))
|
||||
return -EINVAL;
|
||||
|
||||
if ((config->min_height > r.height) || (r.height > config->max_height))
|
||||
return -EINVAL;
|
||||
|
||||
fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
|
||||
if (IS_ERR(fb)) {
|
||||
DRM_DEBUG_KMS("could not create framebuffer\n");
|
||||
return PTR_ERR(fb);
|
||||
}
|
||||
|
||||
mutex_lock(&file_priv->fbs_lock);
|
||||
or->fb_id = fb->base.id;
|
||||
list_add(&fb->filp_head, &file_priv->fbs);
|
||||
DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
|
||||
mutex_unlock(&file_priv->fbs_lock);
|
||||
or->fb_id = r.fb_id;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -3080,7 +3062,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
|
|||
num_planes = drm_format_num_planes(r->pixel_format);
|
||||
|
||||
if (r->width == 0 || r->width % hsub) {
|
||||
DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height);
|
||||
DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -3435,6 +3417,10 @@ void drm_fb_release(struct drm_file *priv)
|
|||
* object with drm_object_attach_property. The returned property object must be
|
||||
* freed with drm_property_destroy.
|
||||
*
|
||||
* Note that the DRM core keeps a per-device list of properties and that, if
|
||||
* drm_mode_config_cleanup() is called, it will destroy all properties created
|
||||
* by the driver.
|
||||
*
|
||||
* Returns:
|
||||
* A pointer to the newly created property on success, NULL on failure.
|
||||
*/
|
||||
|
@ -3611,7 +3597,7 @@ static struct drm_property *property_create_range(struct drm_device *dev,
|
|||
* object with drm_object_attach_property. The returned property object must be
|
||||
* freed with drm_property_destroy.
|
||||
*
|
||||
* Userspace is allowed to set any interger value in the (min, max) range
|
||||
* Userspace is allowed to set any integer value in the (min, max) range
|
||||
* inclusive.
|
||||
*
|
||||
* Returns:
|
||||
|
|
|
@ -39,198 +39,6 @@
|
|||
* blocks, ...
|
||||
*/
|
||||
|
||||
/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
|
||||
static int
|
||||
i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
|
||||
uint8_t write_byte, uint8_t *read_byte)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int ret;
|
||||
|
||||
ret = (*algo_data->aux_ch)(adapter, mode,
|
||||
write_byte, read_byte);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C over AUX CH
|
||||
*/
|
||||
|
||||
/*
|
||||
* Send the address. If the I2C link is running, this 'restarts'
|
||||
* the connection with the new address, this is used for doing
|
||||
* a write followed by a read (as needed for DDC)
|
||||
*/
|
||||
static int
|
||||
i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int mode = MODE_I2C_START;
|
||||
int ret;
|
||||
|
||||
if (reading)
|
||||
mode |= MODE_I2C_READ;
|
||||
else
|
||||
mode |= MODE_I2C_WRITE;
|
||||
algo_data->address = address;
|
||||
algo_data->running = true;
|
||||
ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop the I2C transaction. This closes out the link, sending
|
||||
* a bare address packet with the MOT bit turned off
|
||||
*/
|
||||
static void
|
||||
i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int mode = MODE_I2C_STOP;
|
||||
|
||||
if (reading)
|
||||
mode |= MODE_I2C_READ;
|
||||
else
|
||||
mode |= MODE_I2C_WRITE;
|
||||
if (algo_data->running) {
|
||||
(void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
|
||||
algo_data->running = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a single byte to the current I2C address, the
|
||||
* the I2C link must be running or this returns -EIO
|
||||
*/
|
||||
static int
|
||||
i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int ret;
|
||||
|
||||
if (!algo_data->running)
|
||||
return -EIO;
|
||||
|
||||
ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a single byte from the current I2C address, the
|
||||
* I2C link must be running or this returns -EIO
|
||||
*/
|
||||
static int
|
||||
i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int ret;
|
||||
|
||||
if (!algo_data->running)
|
||||
return -EIO;
|
||||
|
||||
ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
|
||||
struct i2c_msg *msgs,
|
||||
int num)
|
||||
{
|
||||
int ret = 0;
|
||||
bool reading = false;
|
||||
int m;
|
||||
int b;
|
||||
|
||||
for (m = 0; m < num; m++) {
|
||||
u16 len = msgs[m].len;
|
||||
u8 *buf = msgs[m].buf;
|
||||
reading = (msgs[m].flags & I2C_M_RD) != 0;
|
||||
ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (reading) {
|
||||
for (b = 0; b < len; b++) {
|
||||
ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (b = 0; b < len; b++) {
|
||||
ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
if (ret >= 0)
|
||||
ret = num;
|
||||
i2c_algo_dp_aux_stop(adapter, reading);
|
||||
DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32
|
||||
i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
||||
I2C_FUNC_SMBUS_READ_BLOCK_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
|
||||
I2C_FUNC_10BIT_ADDR;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm i2c_dp_aux_algo = {
|
||||
.master_xfer = i2c_algo_dp_aux_xfer,
|
||||
.functionality = i2c_algo_dp_aux_functionality,
|
||||
};
|
||||
|
||||
static void
|
||||
i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
|
||||
{
|
||||
(void) i2c_algo_dp_aux_address(adapter, 0, false);
|
||||
(void) i2c_algo_dp_aux_stop(adapter, false);
|
||||
}
|
||||
|
||||
static int
|
||||
i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
|
||||
{
|
||||
adapter->algo = &i2c_dp_aux_algo;
|
||||
adapter->retries = 3;
|
||||
i2c_dp_aux_reset_bus(adapter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i2c_dp_aux_add_bus() - register an i2c adapter using the aux ch helper
|
||||
* @adapter: i2c adapter to register
|
||||
*
|
||||
* This registers an i2c adapter that uses dp aux channel as it's underlaying
|
||||
* transport. The driver needs to fill out the &i2c_algo_dp_aux_data structure
|
||||
* and store it in the algo_data member of the @adapter argument. This will be
|
||||
* used by the i2c over dp aux algorithm to drive the hardware.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -ERRNO on failure.
|
||||
*
|
||||
* IMPORTANT:
|
||||
* This interface is deprecated, please switch to the new dp aux helpers and
|
||||
* drm_dp_aux_register().
|
||||
*/
|
||||
int
|
||||
i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = i2c_dp_aux_prepare_bus(adapter);
|
||||
if (error)
|
||||
return error;
|
||||
error = i2c_add_adapter(adapter);
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL(i2c_dp_aux_add_bus);
|
||||
|
||||
/* Helpers for DP link training */
|
||||
static u8 dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
|
||||
{
|
||||
|
@ -654,10 +462,12 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
|||
|
||||
case DP_AUX_I2C_REPLY_NACK:
|
||||
DRM_DEBUG_KMS("I2C nack\n");
|
||||
aux->i2c_nack_count++;
|
||||
return -EREMOTEIO;
|
||||
|
||||
case DP_AUX_I2C_REPLY_DEFER:
|
||||
DRM_DEBUG_KMS("I2C defer\n");
|
||||
aux->i2c_defer_count++;
|
||||
usleep_range(400, 500);
|
||||
continue;
|
||||
|
||||
|
|
|
@ -1011,19 +1011,20 @@ static void drm_dp_check_port_guid(struct drm_dp_mst_branch *mstb,
|
|||
|
||||
static void build_mst_prop_path(struct drm_dp_mst_port *port,
|
||||
struct drm_dp_mst_branch *mstb,
|
||||
char *proppath)
|
||||
char *proppath,
|
||||
size_t proppath_size)
|
||||
{
|
||||
int i;
|
||||
char temp[8];
|
||||
snprintf(proppath, 255, "mst:%d", mstb->mgr->conn_base_id);
|
||||
snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id);
|
||||
for (i = 0; i < (mstb->lct - 1); i++) {
|
||||
int shift = (i % 2) ? 0 : 4;
|
||||
int port_num = mstb->rad[i / 2] >> shift;
|
||||
snprintf(temp, 8, "-%d", port_num);
|
||||
strncat(proppath, temp, 255);
|
||||
snprintf(temp, sizeof(temp), "-%d", port_num);
|
||||
strlcat(proppath, temp, proppath_size);
|
||||
}
|
||||
snprintf(temp, 8, "-%d", port->port_num);
|
||||
strncat(proppath, temp, 255);
|
||||
snprintf(temp, sizeof(temp), "-%d", port->port_num);
|
||||
strlcat(proppath, temp, proppath_size);
|
||||
}
|
||||
|
||||
static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
|
||||
|
@ -1094,7 +1095,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
|
|||
|
||||
if (created && !port->input) {
|
||||
char proppath[255];
|
||||
build_mst_prop_path(port, mstb, proppath);
|
||||
build_mst_prop_path(port, mstb, proppath, sizeof(proppath));
|
||||
port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ static struct idr drm_minors_idr;
|
|||
struct class *drm_class;
|
||||
static struct dentry *drm_debugfs_root;
|
||||
|
||||
void drm_err(const char *func, const char *format, ...)
|
||||
void drm_err(const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
@ -66,7 +66,8 @@ void drm_err(const char *func, const char *format, ...)
|
|||
vaf.fmt = format;
|
||||
vaf.va = &args;
|
||||
|
||||
printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf);
|
||||
printk(KERN_ERR "[" DRM_NAME ":%pf] *ERROR* %pV",
|
||||
__builtin_return_address(0), &vaf);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
|
|
@ -1570,7 +1570,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
|
|||
modeset = &fb_helper->crtc_info[i].mode_set;
|
||||
if (modeset->num_connectors == 0) {
|
||||
BUG_ON(modeset->fb);
|
||||
BUG_ON(modeset->num_connectors);
|
||||
if (modeset->mode)
|
||||
drm_mode_destroy(dev, modeset->mode);
|
||||
modeset->mode = NULL;
|
||||
|
|
|
@ -515,10 +515,12 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
|
|||
size_t total;
|
||||
ssize_t ret;
|
||||
|
||||
ret = wait_event_interruptible(file_priv->event_wait,
|
||||
!list_empty(&file_priv->event_list));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if ((filp->f_flags & O_NONBLOCK) == 0) {
|
||||
ret = wait_event_interruptible(file_priv->event_wait,
|
||||
!list_empty(&file_priv->event_list));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
total = 0;
|
||||
while (drm_dequeue_event(file_priv, total, count, &e)) {
|
||||
|
@ -532,7 +534,7 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
|
|||
e->destroy(e);
|
||||
}
|
||||
|
||||
return total;
|
||||
return total ?: -EAGAIN;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_read);
|
||||
|
||||
|
|
|
@ -1190,7 +1190,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_off);
|
|||
*
|
||||
* This functions restores the vblank interrupt state captured with
|
||||
* drm_vblank_off() again. Note that calls to drm_vblank_on() and
|
||||
* drm_vblank_off() can be unbalanced and so can also be unconditionaly called
|
||||
* drm_vblank_off() can be unbalanced and so can also be unconditionally called
|
||||
* in driver load code to reflect the current hardware state of the crtc.
|
||||
*
|
||||
* This is the legacy version of drm_crtc_vblank_on().
|
||||
|
@ -1237,7 +1237,7 @@ EXPORT_SYMBOL(drm_vblank_on);
|
|||
*
|
||||
* This functions restores the vblank interrupt state captured with
|
||||
* drm_vblank_off() again. Note that calls to drm_vblank_on() and
|
||||
* drm_vblank_off() can be unbalanced and so can also be unconditionaly called
|
||||
* drm_vblank_off() can be unbalanced and so can also be unconditionally called
|
||||
* in driver load code to reflect the current hardware state of the crtc.
|
||||
*
|
||||
* This is the native kms version of drm_vblank_on().
|
||||
|
|
|
@ -914,7 +914,7 @@ EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);
|
|||
*
|
||||
* This function is a helper which can be used to validate modes against size
|
||||
* limitations of the DRM device/connector. If a mode is too big its status
|
||||
* memeber is updated with the appropriate validation failure code. The list
|
||||
* member is updated with the appropriate validation failure code. The list
|
||||
* itself is not changed.
|
||||
*/
|
||||
void drm_mode_validate_size(struct drm_device *dev,
|
||||
|
|
|
@ -328,7 +328,7 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = {
|
|||
*/
|
||||
|
||||
/**
|
||||
* drm_gem_prime_export - helper library implemention of the export callback
|
||||
* drm_gem_prime_export - helper library implementation of the export callback
|
||||
* @dev: drm_device to export from
|
||||
* @obj: GEM object to export
|
||||
* @flags: flags like DRM_CLOEXEC
|
||||
|
@ -483,7 +483,7 @@ out_unlock:
|
|||
EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
|
||||
|
||||
/**
|
||||
* drm_gem_prime_import - helper library implemention of the import callback
|
||||
* drm_gem_prime_import - helper library implementation of the import callback
|
||||
* @dev: drm_device to import into
|
||||
* @dma_buf: dma-buf object to import
|
||||
*
|
||||
|
|
|
@ -118,7 +118,8 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
|
|||
mode->status = MODE_UNVERIFIED;
|
||||
|
||||
if (connector->force) {
|
||||
if (connector->force == DRM_FORCE_ON)
|
||||
if (connector->force == DRM_FORCE_ON ||
|
||||
connector->force == DRM_FORCE_ON_DIGITAL)
|
||||
connector->status = connector_status_connected;
|
||||
else
|
||||
connector->status = connector_status_disconnected;
|
||||
|
|
|
@ -37,6 +37,201 @@
|
|||
#include "gma_display.h"
|
||||
#include <drm/drm_dp_helper.h>
|
||||
|
||||
/**
|
||||
* struct i2c_algo_dp_aux_data - driver interface structure for i2c over dp
|
||||
* aux algorithm
|
||||
* @running: set by the algo indicating whether an i2c is ongoing or whether
|
||||
* the i2c bus is quiescent
|
||||
* @address: i2c target address for the currently ongoing transfer
|
||||
* @aux_ch: driver callback to transfer a single byte of the i2c payload
|
||||
*/
|
||||
struct i2c_algo_dp_aux_data {
|
||||
bool running;
|
||||
u16 address;
|
||||
int (*aux_ch) (struct i2c_adapter *adapter,
|
||||
int mode, uint8_t write_byte,
|
||||
uint8_t *read_byte);
|
||||
};
|
||||
|
||||
/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
|
||||
static int
|
||||
i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
|
||||
uint8_t write_byte, uint8_t *read_byte)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int ret;
|
||||
|
||||
ret = (*algo_data->aux_ch)(adapter, mode,
|
||||
write_byte, read_byte);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C over AUX CH
|
||||
*/
|
||||
|
||||
/*
|
||||
* Send the address. If the I2C link is running, this 'restarts'
|
||||
* the connection with the new address, this is used for doing
|
||||
* a write followed by a read (as needed for DDC)
|
||||
*/
|
||||
static int
|
||||
i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int mode = MODE_I2C_START;
|
||||
int ret;
|
||||
|
||||
if (reading)
|
||||
mode |= MODE_I2C_READ;
|
||||
else
|
||||
mode |= MODE_I2C_WRITE;
|
||||
algo_data->address = address;
|
||||
algo_data->running = true;
|
||||
ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop the I2C transaction. This closes out the link, sending
|
||||
* a bare address packet with the MOT bit turned off
|
||||
*/
|
||||
static void
|
||||
i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int mode = MODE_I2C_STOP;
|
||||
|
||||
if (reading)
|
||||
mode |= MODE_I2C_READ;
|
||||
else
|
||||
mode |= MODE_I2C_WRITE;
|
||||
if (algo_data->running) {
|
||||
(void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
|
||||
algo_data->running = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a single byte to the current I2C address, the
|
||||
* the I2C link must be running or this returns -EIO
|
||||
*/
|
||||
static int
|
||||
i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int ret;
|
||||
|
||||
if (!algo_data->running)
|
||||
return -EIO;
|
||||
|
||||
ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a single byte from the current I2C address, the
|
||||
* I2C link must be running or this returns -EIO
|
||||
*/
|
||||
static int
|
||||
i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int ret;
|
||||
|
||||
if (!algo_data->running)
|
||||
return -EIO;
|
||||
|
||||
ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
|
||||
struct i2c_msg *msgs,
|
||||
int num)
|
||||
{
|
||||
int ret = 0;
|
||||
bool reading = false;
|
||||
int m;
|
||||
int b;
|
||||
|
||||
for (m = 0; m < num; m++) {
|
||||
u16 len = msgs[m].len;
|
||||
u8 *buf = msgs[m].buf;
|
||||
reading = (msgs[m].flags & I2C_M_RD) != 0;
|
||||
ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (reading) {
|
||||
for (b = 0; b < len; b++) {
|
||||
ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (b = 0; b < len; b++) {
|
||||
ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
if (ret >= 0)
|
||||
ret = num;
|
||||
i2c_algo_dp_aux_stop(adapter, reading);
|
||||
DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32
|
||||
i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
||||
I2C_FUNC_SMBUS_READ_BLOCK_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
|
||||
I2C_FUNC_10BIT_ADDR;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm i2c_dp_aux_algo = {
|
||||
.master_xfer = i2c_algo_dp_aux_xfer,
|
||||
.functionality = i2c_algo_dp_aux_functionality,
|
||||
};
|
||||
|
||||
static void
|
||||
i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
|
||||
{
|
||||
(void) i2c_algo_dp_aux_address(adapter, 0, false);
|
||||
(void) i2c_algo_dp_aux_stop(adapter, false);
|
||||
}
|
||||
|
||||
static int
|
||||
i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
|
||||
{
|
||||
adapter->algo = &i2c_dp_aux_algo;
|
||||
adapter->retries = 3;
|
||||
i2c_dp_aux_reset_bus(adapter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: This is the old dp aux helper, gma500 is the last driver that needs to
|
||||
* be ported over to the new helper code in drm_dp_helper.c like i915 or radeon.
|
||||
*/
|
||||
static int __deprecated
|
||||
i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = i2c_dp_aux_prepare_bus(adapter);
|
||||
if (error)
|
||||
return error;
|
||||
error = i2c_add_adapter(adapter);
|
||||
return error;
|
||||
}
|
||||
|
||||
#define _wait_for(COND, MS, W) ({ \
|
||||
unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \
|
||||
int ret__ = 0; \
|
||||
|
|
|
@ -1631,57 +1631,8 @@ static int psb_intel_sdvo_get_modes(struct drm_connector *connector)
|
|||
return !list_empty(&connector->probed_modes);
|
||||
}
|
||||
|
||||
static void
|
||||
psb_intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
|
||||
{
|
||||
struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector);
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
if (psb_intel_sdvo_connector->left)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->left);
|
||||
if (psb_intel_sdvo_connector->right)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->right);
|
||||
if (psb_intel_sdvo_connector->top)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->top);
|
||||
if (psb_intel_sdvo_connector->bottom)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->bottom);
|
||||
if (psb_intel_sdvo_connector->hpos)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->hpos);
|
||||
if (psb_intel_sdvo_connector->vpos)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->vpos);
|
||||
if (psb_intel_sdvo_connector->saturation)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->saturation);
|
||||
if (psb_intel_sdvo_connector->contrast)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->contrast);
|
||||
if (psb_intel_sdvo_connector->hue)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->hue);
|
||||
if (psb_intel_sdvo_connector->sharpness)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->sharpness);
|
||||
if (psb_intel_sdvo_connector->flicker_filter)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter);
|
||||
if (psb_intel_sdvo_connector->flicker_filter_2d)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_2d);
|
||||
if (psb_intel_sdvo_connector->flicker_filter_adaptive)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_adaptive);
|
||||
if (psb_intel_sdvo_connector->tv_luma_filter)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->tv_luma_filter);
|
||||
if (psb_intel_sdvo_connector->tv_chroma_filter)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->tv_chroma_filter);
|
||||
if (psb_intel_sdvo_connector->dot_crawl)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->dot_crawl);
|
||||
if (psb_intel_sdvo_connector->brightness)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->brightness);
|
||||
}
|
||||
|
||||
static void psb_intel_sdvo_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector);
|
||||
|
||||
if (psb_intel_sdvo_connector->tv_format)
|
||||
drm_property_destroy(connector->dev,
|
||||
psb_intel_sdvo_connector->tv_format);
|
||||
|
||||
psb_intel_sdvo_destroy_enhance_property(connector);
|
||||
drm_connector_unregister(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
* those commands required by the parser. This generally works because command
|
||||
* opcode ranges have standard command length encodings. So for commands that
|
||||
* the parser does not need to check, it can easily skip them. This is
|
||||
* implementated via a per-ring length decoding vfunc.
|
||||
* implemented via a per-ring length decoding vfunc.
|
||||
*
|
||||
* Unfortunately, there are a number of commands that do not follow the standard
|
||||
* length encoding for their opcode range, primarily amongst the MI_* commands.
|
||||
|
@ -838,7 +838,7 @@ finish:
|
|||
* @ring: the ring in question
|
||||
*
|
||||
* Only certain platforms require software batch buffer command parsing, and
|
||||
* only when enabled via module paramter.
|
||||
* only when enabled via module parameter.
|
||||
*
|
||||
* Return: true if the ring requires software command parsing
|
||||
*/
|
||||
|
|
|
@ -672,7 +672,7 @@ enum punit_power_well {
|
|||
* need to be accessed during AUX communication,
|
||||
*
|
||||
* Generally the common lane corresponds to the pipe and
|
||||
* the spline (PCS/TX) correponds to the port.
|
||||
* the spline (PCS/TX) corresponds to the port.
|
||||
*
|
||||
* For dual channel PHY (VLV/CHV):
|
||||
*
|
||||
|
|
|
@ -1660,7 +1660,7 @@ static uint32_t get_lr_context_size(struct intel_engine_cs *ring)
|
|||
* the creation is a deferred call: it's better to make sure first that we need to use
|
||||
* a given ring with the context.
|
||||
*
|
||||
* Return: non-zero on eror.
|
||||
* Return: non-zero on error.
|
||||
*/
|
||||
int intel_lr_context_deferred_create(struct intel_context *ctx,
|
||||
struct intel_engine_cs *ring)
|
||||
|
|
|
@ -1991,57 +1991,10 @@ static int intel_sdvo_get_modes(struct drm_connector *connector)
|
|||
return !list_empty(&connector->probed_modes);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
if (intel_sdvo_connector->left)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->left);
|
||||
if (intel_sdvo_connector->right)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->right);
|
||||
if (intel_sdvo_connector->top)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->top);
|
||||
if (intel_sdvo_connector->bottom)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->bottom);
|
||||
if (intel_sdvo_connector->hpos)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->hpos);
|
||||
if (intel_sdvo_connector->vpos)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->vpos);
|
||||
if (intel_sdvo_connector->saturation)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->saturation);
|
||||
if (intel_sdvo_connector->contrast)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->contrast);
|
||||
if (intel_sdvo_connector->hue)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->hue);
|
||||
if (intel_sdvo_connector->sharpness)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->sharpness);
|
||||
if (intel_sdvo_connector->flicker_filter)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->flicker_filter);
|
||||
if (intel_sdvo_connector->flicker_filter_2d)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->flicker_filter_2d);
|
||||
if (intel_sdvo_connector->flicker_filter_adaptive)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->flicker_filter_adaptive);
|
||||
if (intel_sdvo_connector->tv_luma_filter)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->tv_luma_filter);
|
||||
if (intel_sdvo_connector->tv_chroma_filter)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->tv_chroma_filter);
|
||||
if (intel_sdvo_connector->dot_crawl)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->dot_crawl);
|
||||
if (intel_sdvo_connector->brightness)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->brightness);
|
||||
}
|
||||
|
||||
static void intel_sdvo_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
|
||||
|
||||
if (intel_sdvo_connector->tv_format)
|
||||
drm_property_destroy(connector->dev,
|
||||
intel_sdvo_connector->tv_format);
|
||||
|
||||
intel_sdvo_destroy_enhance_property(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(intel_sdvo_connector);
|
||||
}
|
||||
|
|
|
@ -125,8 +125,8 @@ struct dma_buf_attachment;
|
|||
extern __printf(2, 3)
|
||||
void drm_ut_debug_printk(const char *function_name,
|
||||
const char *format, ...);
|
||||
extern __printf(2, 3)
|
||||
void drm_err(const char *func, const char *format, ...);
|
||||
extern __printf(1, 2)
|
||||
void drm_err(const char *format, ...);
|
||||
|
||||
/***********************************************************************/
|
||||
/** \name DRM template customization defaults */
|
||||
|
@ -155,7 +155,7 @@ void drm_err(const char *func, const char *format, ...);
|
|||
* \param arg arguments
|
||||
*/
|
||||
#define DRM_ERROR(fmt, ...) \
|
||||
drm_err(__func__, fmt, ##__VA_ARGS__)
|
||||
drm_err(fmt, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Rate limited error output. Like DRM_ERROR() but won't flood the log.
|
||||
|
@ -170,7 +170,7 @@ void drm_err(const char *func, const char *format, ...);
|
|||
DEFAULT_RATELIMIT_BURST); \
|
||||
\
|
||||
if (__ratelimit(&_rs)) \
|
||||
drm_err(__func__, fmt, ##__VA_ARGS__); \
|
||||
drm_err(fmt, ##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define DRM_INFO(fmt, ...) \
|
||||
|
|
|
@ -405,26 +405,6 @@
|
|||
#define MODE_I2C_READ 4
|
||||
#define MODE_I2C_STOP 8
|
||||
|
||||
/**
|
||||
* struct i2c_algo_dp_aux_data - driver interface structure for i2c over dp
|
||||
* aux algorithm
|
||||
* @running: set by the algo indicating whether an i2c is ongoing or whether
|
||||
* the i2c bus is quiescent
|
||||
* @address: i2c target address for the currently ongoing transfer
|
||||
* @aux_ch: driver callback to transfer a single byte of the i2c payload
|
||||
*/
|
||||
struct i2c_algo_dp_aux_data {
|
||||
bool running;
|
||||
u16 address;
|
||||
int (*aux_ch) (struct i2c_adapter *adapter,
|
||||
int mode, uint8_t write_byte,
|
||||
uint8_t *read_byte);
|
||||
};
|
||||
|
||||
int
|
||||
i2c_dp_aux_add_bus(struct i2c_adapter *adapter);
|
||||
|
||||
|
||||
#define DP_LINK_STATUS_SIZE 6
|
||||
bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE],
|
||||
int lane_count);
|
||||
|
@ -551,6 +531,7 @@ struct drm_dp_aux {
|
|||
struct mutex hw_mutex;
|
||||
ssize_t (*transfer)(struct drm_dp_aux *aux,
|
||||
struct drm_dp_aux_msg *msg);
|
||||
unsigned i2c_nack_count, i2c_defer_count;
|
||||
};
|
||||
|
||||
ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
struct drm_dp_mst_branch;
|
||||
|
||||
/**
|
||||
* struct drm_dp_vcpi - Virtual Channel Payload Identifer
|
||||
* struct drm_dp_vcpi - Virtual Channel Payload Identifier
|
||||
* @vcpi: Virtual channel ID.
|
||||
* @pbn: Payload Bandwidth Number for this channel
|
||||
* @aligned_pbn: PBN aligned with slot size
|
||||
|
|
|
@ -207,6 +207,61 @@ struct detailed_timing {
|
|||
#define DRM_EDID_HDMI_DC_30 (1 << 4)
|
||||
#define DRM_EDID_HDMI_DC_Y444 (1 << 3)
|
||||
|
||||
/* ELD Header Block */
|
||||
#define DRM_ELD_HEADER_BLOCK_SIZE 4
|
||||
|
||||
#define DRM_ELD_VER 0
|
||||
# define DRM_ELD_VER_SHIFT 3
|
||||
# define DRM_ELD_VER_MASK (0x1f << 3)
|
||||
|
||||
#define DRM_ELD_BASELINE_ELD_LEN 2 /* in dwords! */
|
||||
|
||||
/* ELD Baseline Block for ELD_Ver == 2 */
|
||||
#define DRM_ELD_CEA_EDID_VER_MNL 4
|
||||
# define DRM_ELD_CEA_EDID_VER_SHIFT 5
|
||||
# define DRM_ELD_CEA_EDID_VER_MASK (7 << 5)
|
||||
# define DRM_ELD_CEA_EDID_VER_NONE (0 << 5)
|
||||
# define DRM_ELD_CEA_EDID_VER_CEA861 (1 << 5)
|
||||
# define DRM_ELD_CEA_EDID_VER_CEA861A (2 << 5)
|
||||
# define DRM_ELD_CEA_EDID_VER_CEA861BCD (3 << 5)
|
||||
# define DRM_ELD_MNL_SHIFT 0
|
||||
# define DRM_ELD_MNL_MASK (0x1f << 0)
|
||||
|
||||
#define DRM_ELD_SAD_COUNT_CONN_TYPE 5
|
||||
# define DRM_ELD_SAD_COUNT_SHIFT 4
|
||||
# define DRM_ELD_SAD_COUNT_MASK (0xf << 4)
|
||||
# define DRM_ELD_CONN_TYPE_SHIFT 2
|
||||
# define DRM_ELD_CONN_TYPE_MASK (3 << 2)
|
||||
# define DRM_ELD_CONN_TYPE_HDMI (0 << 2)
|
||||
# define DRM_ELD_CONN_TYPE_DP (1 << 2)
|
||||
# define DRM_ELD_SUPPORTS_AI (1 << 1)
|
||||
# define DRM_ELD_SUPPORTS_HDCP (1 << 0)
|
||||
|
||||
#define DRM_ELD_AUD_SYNCH_DELAY 6 /* in units of 2 ms */
|
||||
# define DRM_ELD_AUD_SYNCH_DELAY_MAX 0xfa /* 500 ms */
|
||||
|
||||
#define DRM_ELD_SPEAKER 7
|
||||
# define DRM_ELD_SPEAKER_RLRC (1 << 6)
|
||||
# define DRM_ELD_SPEAKER_FLRC (1 << 5)
|
||||
# define DRM_ELD_SPEAKER_RC (1 << 4)
|
||||
# define DRM_ELD_SPEAKER_RLR (1 << 3)
|
||||
# define DRM_ELD_SPEAKER_FC (1 << 2)
|
||||
# define DRM_ELD_SPEAKER_LFE (1 << 1)
|
||||
# define DRM_ELD_SPEAKER_FLR (1 << 0)
|
||||
|
||||
#define DRM_ELD_PORT_ID 8 /* offsets 8..15 inclusive */
|
||||
# define DRM_ELD_PORT_ID_LEN 8
|
||||
|
||||
#define DRM_ELD_MANUFACTURER_NAME0 16
|
||||
#define DRM_ELD_MANUFACTURER_NAME1 17
|
||||
|
||||
#define DRM_ELD_PRODUCT_CODE0 18
|
||||
#define DRM_ELD_PRODUCT_CODE1 19
|
||||
|
||||
#define DRM_ELD_MONITOR_NAME_STRING 20 /* offsets 20..(20+mnl-1) inclusive */
|
||||
|
||||
#define DRM_ELD_CEA_SAD(mnl, sad) (20 + (mnl) + 3 * (sad))
|
||||
|
||||
struct edid {
|
||||
u8 header[8];
|
||||
/* Vendor & product info */
|
||||
|
@ -279,4 +334,51 @@ int
|
|||
drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
|
||||
const struct drm_display_mode *mode);
|
||||
|
||||
/**
|
||||
* drm_eld_mnl - Get ELD monitor name length in bytes.
|
||||
* @eld: pointer to an eld memory structure with mnl set
|
||||
*/
|
||||
static inline int drm_eld_mnl(const uint8_t *eld)
|
||||
{
|
||||
return (eld[DRM_ELD_CEA_EDID_VER_MNL] & DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_eld_sad_count - Get ELD SAD count.
|
||||
* @eld: pointer to an eld memory structure with sad_count set
|
||||
*/
|
||||
static inline int drm_eld_sad_count(const uint8_t *eld)
|
||||
{
|
||||
return (eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_SAD_COUNT_MASK) >>
|
||||
DRM_ELD_SAD_COUNT_SHIFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_eld_calc_baseline_block_size - Calculate baseline block size in bytes
|
||||
* @eld: pointer to an eld memory structure with mnl and sad_count set
|
||||
*
|
||||
* This is a helper for determining the payload size of the baseline block, in
|
||||
* bytes, for e.g. setting the Baseline_ELD_Len field in the ELD header block.
|
||||
*/
|
||||
static inline int drm_eld_calc_baseline_block_size(const uint8_t *eld)
|
||||
{
|
||||
return DRM_ELD_MONITOR_NAME_STRING - DRM_ELD_HEADER_BLOCK_SIZE +
|
||||
drm_eld_mnl(eld) + drm_eld_sad_count(eld) * 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_eld_size - Get ELD size in bytes
|
||||
* @eld: pointer to a complete eld memory structure
|
||||
*
|
||||
* The returned value does not include the vendor block. It's vendor specific,
|
||||
* and comprises of the remaining bytes in the ELD memory buffer after
|
||||
* drm_eld_size() bytes of header and baseline block.
|
||||
*
|
||||
* The returned value is guaranteed to be a multiple of 4.
|
||||
*/
|
||||
static inline int drm_eld_size(const uint8_t *eld)
|
||||
{
|
||||
return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4;
|
||||
}
|
||||
|
||||
#endif /* __DRM_EDID_H__ */
|
||||
|
|
Loading…
Reference in New Issue