Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Pull drm fixes from Dave Airlie: "Bunch of fixes all over the place, all pretty small: amdgpu, i915, exynos, one qxl and one vmwgfx. There is also a bunch of mst fixes, I left some cleanups in the series as I didn't think it was worth splitting up the tested series" * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: (37 commits) drm/dp/mst: add some defines for logical/physical ports drm/dp/mst: drop cancel work sync in the mstb destroy path (v2) drm/dp/mst: split connector registration into two parts (v2) drm/dp/mst: update the link_address_sent before sending the link address (v3) drm/dp/mst: fixup handling hotplug on port removal. drm/dp/mst: don't pass port into the path builder function drm/radeon: drop radeon_fb_helper_set_par drm: handle cursor_set2 in restore_fbdev_mode drm/exynos: Staticize local function in exynos_drm_gem.c drm/exynos: fimd: actually disable dp clock drm/exynos: dp: remove suspend/resume functions drm/qxl: recreate the primary surface when the bo is not primary drm/amdgpu: only print meaningful VM faults drm/amdgpu/cgs: remove import_gpu_mem drm/i915: Call non-locking version of drm_kms_helper_poll_enable(), v2 drm: Add a non-locking version of drm_kms_helper_poll_enable(), v2 drm/vmwgfx: Fix a command submission hang regression drm/exynos: remove unused mode_fixup() code drm/exynos: remove decon_mode_fixup() drm/exynos: remove fimd_mode_fixup() ...
This commit is contained in:
commit
14f97d9713
@ -208,44 +208,6 @@ static int amdgpu_cgs_alloc_gpu_mem(void *cgs_device,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int amdgpu_cgs_import_gpu_mem(void *cgs_device, int dmabuf_fd,
|
|
||||||
cgs_handle_t *handle)
|
|
||||||
{
|
|
||||||
CGS_FUNC_ADEV;
|
|
||||||
int r;
|
|
||||||
uint32_t dma_handle;
|
|
||||||
struct drm_gem_object *obj;
|
|
||||||
struct amdgpu_bo *bo;
|
|
||||||
struct drm_device *dev = adev->ddev;
|
|
||||||
struct drm_file *file_priv = NULL, *priv;
|
|
||||||
|
|
||||||
mutex_lock(&dev->struct_mutex);
|
|
||||||
list_for_each_entry(priv, &dev->filelist, lhead) {
|
|
||||||
rcu_read_lock();
|
|
||||||
if (priv->pid == get_pid(task_pid(current)))
|
|
||||||
file_priv = priv;
|
|
||||||
rcu_read_unlock();
|
|
||||||
if (file_priv)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mutex_unlock(&dev->struct_mutex);
|
|
||||||
r = dev->driver->prime_fd_to_handle(dev,
|
|
||||||
file_priv, dmabuf_fd,
|
|
||||||
&dma_handle);
|
|
||||||
spin_lock(&file_priv->table_lock);
|
|
||||||
|
|
||||||
/* Check if we currently have a reference on the object */
|
|
||||||
obj = idr_find(&file_priv->object_idr, dma_handle);
|
|
||||||
if (obj == NULL) {
|
|
||||||
spin_unlock(&file_priv->table_lock);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
spin_unlock(&file_priv->table_lock);
|
|
||||||
bo = gem_to_amdgpu_bo(obj);
|
|
||||||
*handle = (cgs_handle_t)bo;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int amdgpu_cgs_free_gpu_mem(void *cgs_device, cgs_handle_t handle)
|
static int amdgpu_cgs_free_gpu_mem(void *cgs_device, cgs_handle_t handle)
|
||||||
{
|
{
|
||||||
struct amdgpu_bo *obj = (struct amdgpu_bo *)handle;
|
struct amdgpu_bo *obj = (struct amdgpu_bo *)handle;
|
||||||
@ -810,7 +772,6 @@ static const struct cgs_ops amdgpu_cgs_ops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct cgs_os_ops amdgpu_cgs_os_ops = {
|
static const struct cgs_os_ops amdgpu_cgs_os_ops = {
|
||||||
amdgpu_cgs_import_gpu_mem,
|
|
||||||
amdgpu_cgs_add_irq_source,
|
amdgpu_cgs_add_irq_source,
|
||||||
amdgpu_cgs_irq_get,
|
amdgpu_cgs_irq_get,
|
||||||
amdgpu_cgs_irq_put
|
amdgpu_cgs_irq_put
|
||||||
|
@ -156,7 +156,8 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
|
|||||||
uint64_t *chunk_array_user;
|
uint64_t *chunk_array_user;
|
||||||
uint64_t *chunk_array;
|
uint64_t *chunk_array;
|
||||||
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
|
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
|
||||||
unsigned size, i;
|
unsigned size;
|
||||||
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (cs->in.num_chunks == 0)
|
if (cs->in.num_chunks == 0)
|
||||||
|
@ -1279,8 +1279,7 @@ amdgpu_atombios_encoder_setup_dig(struct drm_encoder *encoder, int action)
|
|||||||
amdgpu_atombios_encoder_setup_dig_encoder(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
|
amdgpu_atombios_encoder_setup_dig_encoder(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
|
||||||
}
|
}
|
||||||
if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
|
if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
|
||||||
amdgpu_atombios_encoder_setup_dig_transmitter(encoder,
|
amdgpu_atombios_encoder_set_backlight_level(amdgpu_encoder, dig->backlight_level);
|
||||||
ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
|
|
||||||
if (ext_encoder)
|
if (ext_encoder)
|
||||||
amdgpu_atombios_encoder_setup_external_encoder(encoder, ext_encoder, ATOM_ENABLE);
|
amdgpu_atombios_encoder_setup_external_encoder(encoder, ext_encoder, ATOM_ENABLE);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1262,6 +1262,12 @@ static int gmc_v7_0_process_interrupt(struct amdgpu_device *adev,
|
|||||||
addr = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR);
|
addr = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR);
|
||||||
status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS);
|
status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS);
|
||||||
mc_client = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_MCCLIENT);
|
mc_client = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_MCCLIENT);
|
||||||
|
/* reset addr and status */
|
||||||
|
WREG32_P(mmVM_CONTEXT1_CNTL2, 1, ~1);
|
||||||
|
|
||||||
|
if (!addr && !status)
|
||||||
|
return 0;
|
||||||
|
|
||||||
dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
|
dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
|
||||||
entry->src_id, entry->src_data);
|
entry->src_id, entry->src_data);
|
||||||
dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n",
|
dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n",
|
||||||
@ -1269,8 +1275,6 @@ static int gmc_v7_0_process_interrupt(struct amdgpu_device *adev,
|
|||||||
dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
|
dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
|
||||||
status);
|
status);
|
||||||
gmc_v7_0_vm_decode_fault(adev, status, addr, mc_client);
|
gmc_v7_0_vm_decode_fault(adev, status, addr, mc_client);
|
||||||
/* reset addr and status */
|
|
||||||
WREG32_P(mmVM_CONTEXT1_CNTL2, 1, ~1);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1262,6 +1262,12 @@ static int gmc_v8_0_process_interrupt(struct amdgpu_device *adev,
|
|||||||
addr = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR);
|
addr = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR);
|
||||||
status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS);
|
status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS);
|
||||||
mc_client = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_MCCLIENT);
|
mc_client = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_MCCLIENT);
|
||||||
|
/* reset addr and status */
|
||||||
|
WREG32_P(mmVM_CONTEXT1_CNTL2, 1, ~1);
|
||||||
|
|
||||||
|
if (!addr && !status)
|
||||||
|
return 0;
|
||||||
|
|
||||||
dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
|
dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
|
||||||
entry->src_id, entry->src_data);
|
entry->src_id, entry->src_data);
|
||||||
dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n",
|
dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n",
|
||||||
@ -1269,8 +1275,6 @@ static int gmc_v8_0_process_interrupt(struct amdgpu_device *adev,
|
|||||||
dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
|
dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
|
||||||
status);
|
status);
|
||||||
gmc_v8_0_vm_decode_fault(adev, status, addr, mc_client);
|
gmc_v8_0_vm_decode_fault(adev, status, addr, mc_client);
|
||||||
/* reset addr and status */
|
|
||||||
WREG32_P(mmVM_CONTEXT1_CNTL2, 1, ~1);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -26,19 +26,6 @@
|
|||||||
|
|
||||||
#include "cgs_common.h"
|
#include "cgs_common.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* cgs_import_gpu_mem() - Import dmabuf handle
|
|
||||||
* @cgs_device: opaque device handle
|
|
||||||
* @dmabuf_fd: DMABuf file descriptor
|
|
||||||
* @handle: memory handle (output)
|
|
||||||
*
|
|
||||||
* Must be called in the process context that dmabuf_fd belongs to.
|
|
||||||
*
|
|
||||||
* Return: 0 on success, -errno otherwise
|
|
||||||
*/
|
|
||||||
typedef int (*cgs_import_gpu_mem_t)(void *cgs_device, int dmabuf_fd,
|
|
||||||
cgs_handle_t *handle);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cgs_irq_source_set_func() - Callback for enabling/disabling interrupt sources
|
* cgs_irq_source_set_func() - Callback for enabling/disabling interrupt sources
|
||||||
* @private_data: private data provided to cgs_add_irq_source
|
* @private_data: private data provided to cgs_add_irq_source
|
||||||
@ -114,16 +101,12 @@ typedef int (*cgs_irq_get_t)(void *cgs_device, unsigned src_id, unsigned type);
|
|||||||
typedef int (*cgs_irq_put_t)(void *cgs_device, unsigned src_id, unsigned type);
|
typedef int (*cgs_irq_put_t)(void *cgs_device, unsigned src_id, unsigned type);
|
||||||
|
|
||||||
struct cgs_os_ops {
|
struct cgs_os_ops {
|
||||||
cgs_import_gpu_mem_t import_gpu_mem;
|
|
||||||
|
|
||||||
/* IRQ handling */
|
/* IRQ handling */
|
||||||
cgs_add_irq_source_t add_irq_source;
|
cgs_add_irq_source_t add_irq_source;
|
||||||
cgs_irq_get_t irq_get;
|
cgs_irq_get_t irq_get;
|
||||||
cgs_irq_put_t irq_put;
|
cgs_irq_put_t irq_put;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define cgs_import_gpu_mem(dev,dmabuf_fd,handle) \
|
|
||||||
CGS_OS_CALL(import_gpu_mem,dev,dmabuf_fd,handle)
|
|
||||||
#define cgs_add_irq_source(dev,src_id,num_types,set,handler,private_data) \
|
#define cgs_add_irq_source(dev,src_id,num_types,set,handler,private_data) \
|
||||||
CGS_OS_CALL(add_irq_source,dev,src_id,num_types,set,handler, \
|
CGS_OS_CALL(add_irq_source,dev,src_id,num_types,set,handler, \
|
||||||
private_data)
|
private_data)
|
||||||
|
@ -53,8 +53,8 @@ static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
|
|||||||
struct drm_dp_mst_port *port,
|
struct drm_dp_mst_port *port,
|
||||||
int offset, int size, u8 *bytes);
|
int offset, int size, u8 *bytes);
|
||||||
|
|
||||||
static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
|
static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
|
||||||
struct drm_dp_mst_branch *mstb);
|
struct drm_dp_mst_branch *mstb);
|
||||||
static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
|
static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
|
||||||
struct drm_dp_mst_branch *mstb,
|
struct drm_dp_mst_branch *mstb,
|
||||||
struct drm_dp_mst_port *port);
|
struct drm_dp_mst_port *port);
|
||||||
@ -804,8 +804,6 @@ static void drm_dp_destroy_mst_branch_device(struct kref *kref)
|
|||||||
struct drm_dp_mst_port *port, *tmp;
|
struct drm_dp_mst_port *port, *tmp;
|
||||||
bool wake_tx = false;
|
bool wake_tx = false;
|
||||||
|
|
||||||
cancel_work_sync(&mstb->mgr->work);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* destroy all ports - don't need lock
|
* destroy all ports - don't need lock
|
||||||
* as there are no more references to the mst branch
|
* as there are no more references to the mst branch
|
||||||
@ -863,29 +861,33 @@ static void drm_dp_destroy_port(struct kref *kref)
|
|||||||
{
|
{
|
||||||
struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref);
|
struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref);
|
||||||
struct drm_dp_mst_topology_mgr *mgr = port->mgr;
|
struct drm_dp_mst_topology_mgr *mgr = port->mgr;
|
||||||
|
|
||||||
if (!port->input) {
|
if (!port->input) {
|
||||||
port->vcpi.num_slots = 0;
|
port->vcpi.num_slots = 0;
|
||||||
|
|
||||||
kfree(port->cached_edid);
|
kfree(port->cached_edid);
|
||||||
|
|
||||||
/* we can't destroy the connector here, as
|
/*
|
||||||
we might be holding the mode_config.mutex
|
* The only time we don't have a connector
|
||||||
from an EDID retrieval */
|
* on an output port is if the connector init
|
||||||
|
* fails.
|
||||||
|
*/
|
||||||
if (port->connector) {
|
if (port->connector) {
|
||||||
|
/* we can't destroy the connector here, as
|
||||||
|
* we might be holding the mode_config.mutex
|
||||||
|
* from an EDID retrieval */
|
||||||
|
|
||||||
mutex_lock(&mgr->destroy_connector_lock);
|
mutex_lock(&mgr->destroy_connector_lock);
|
||||||
list_add(&port->next, &mgr->destroy_connector_list);
|
list_add(&port->next, &mgr->destroy_connector_list);
|
||||||
mutex_unlock(&mgr->destroy_connector_lock);
|
mutex_unlock(&mgr->destroy_connector_lock);
|
||||||
schedule_work(&mgr->destroy_connector_work);
|
schedule_work(&mgr->destroy_connector_work);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/* no need to clean up vcpi
|
||||||
|
* as if we have no connector we never setup a vcpi */
|
||||||
drm_dp_port_teardown_pdt(port, port->pdt);
|
drm_dp_port_teardown_pdt(port, port->pdt);
|
||||||
|
|
||||||
if (!port->input && port->vcpi.vcpi > 0)
|
|
||||||
drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
|
|
||||||
}
|
}
|
||||||
kfree(port);
|
kfree(port);
|
||||||
|
|
||||||
(*mgr->cbs->hotplug)(mgr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drm_dp_put_port(struct drm_dp_mst_port *port)
|
static void drm_dp_put_port(struct drm_dp_mst_port *port)
|
||||||
@ -1027,8 +1029,8 @@ 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,
|
static void build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
|
||||||
struct drm_dp_mst_branch *mstb,
|
int pnum,
|
||||||
char *proppath,
|
char *proppath,
|
||||||
size_t proppath_size)
|
size_t proppath_size)
|
||||||
{
|
{
|
||||||
@ -1041,7 +1043,7 @@ static void build_mst_prop_path(struct drm_dp_mst_port *port,
|
|||||||
snprintf(temp, sizeof(temp), "-%d", port_num);
|
snprintf(temp, sizeof(temp), "-%d", port_num);
|
||||||
strlcat(proppath, temp, proppath_size);
|
strlcat(proppath, temp, proppath_size);
|
||||||
}
|
}
|
||||||
snprintf(temp, sizeof(temp), "-%d", port->port_num);
|
snprintf(temp, sizeof(temp), "-%d", pnum);
|
||||||
strlcat(proppath, temp, proppath_size);
|
strlcat(proppath, temp, proppath_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1105,22 +1107,32 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
|
|||||||
drm_dp_port_teardown_pdt(port, old_pdt);
|
drm_dp_port_teardown_pdt(port, old_pdt);
|
||||||
|
|
||||||
ret = drm_dp_port_setup_pdt(port);
|
ret = drm_dp_port_setup_pdt(port);
|
||||||
if (ret == true) {
|
if (ret == true)
|
||||||
drm_dp_send_link_address(mstb->mgr, port->mstb);
|
drm_dp_send_link_address(mstb->mgr, port->mstb);
|
||||||
port->mstb->link_address_sent = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (created && !port->input) {
|
if (created && !port->input) {
|
||||||
char proppath[255];
|
char proppath[255];
|
||||||
build_mst_prop_path(port, mstb, proppath, sizeof(proppath));
|
|
||||||
port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
|
|
||||||
|
|
||||||
if (port->port_num >= 8) {
|
build_mst_prop_path(mstb, port->port_num, proppath, sizeof(proppath));
|
||||||
port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
|
port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
|
||||||
|
if (!port->connector) {
|
||||||
|
/* remove it from the port list */
|
||||||
|
mutex_lock(&mstb->mgr->lock);
|
||||||
|
list_del(&port->next);
|
||||||
|
mutex_unlock(&mstb->mgr->lock);
|
||||||
|
/* drop port list reference */
|
||||||
|
drm_dp_put_port(port);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (port->port_num >= DP_MST_LOGICAL_PORT_0) {
|
||||||
|
port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
|
||||||
|
drm_mode_connector_set_tile_property(port->connector);
|
||||||
|
}
|
||||||
|
(*mstb->mgr->cbs->register_connector)(port->connector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
/* put reference to this port */
|
/* put reference to this port */
|
||||||
drm_dp_put_port(port);
|
drm_dp_put_port(port);
|
||||||
}
|
}
|
||||||
@ -1202,10 +1214,9 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m
|
|||||||
{
|
{
|
||||||
struct drm_dp_mst_port *port;
|
struct drm_dp_mst_port *port;
|
||||||
struct drm_dp_mst_branch *mstb_child;
|
struct drm_dp_mst_branch *mstb_child;
|
||||||
if (!mstb->link_address_sent) {
|
if (!mstb->link_address_sent)
|
||||||
drm_dp_send_link_address(mgr, mstb);
|
drm_dp_send_link_address(mgr, mstb);
|
||||||
mstb->link_address_sent = true;
|
|
||||||
}
|
|
||||||
list_for_each_entry(port, &mstb->ports, next) {
|
list_for_each_entry(port, &mstb->ports, next) {
|
||||||
if (port->input)
|
if (port->input)
|
||||||
continue;
|
continue;
|
||||||
@ -1458,8 +1469,8 @@ static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
|
|||||||
mutex_unlock(&mgr->qlock);
|
mutex_unlock(&mgr->qlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
|
static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
|
||||||
struct drm_dp_mst_branch *mstb)
|
struct drm_dp_mst_branch *mstb)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
struct drm_dp_sideband_msg_tx *txmsg;
|
struct drm_dp_sideband_msg_tx *txmsg;
|
||||||
@ -1467,11 +1478,12 @@ static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
|
|||||||
|
|
||||||
txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
|
txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
|
||||||
if (!txmsg)
|
if (!txmsg)
|
||||||
return -ENOMEM;
|
return;
|
||||||
|
|
||||||
txmsg->dst = mstb;
|
txmsg->dst = mstb;
|
||||||
len = build_link_address(txmsg);
|
len = build_link_address(txmsg);
|
||||||
|
|
||||||
|
mstb->link_address_sent = true;
|
||||||
drm_dp_queue_down_tx(mgr, txmsg);
|
drm_dp_queue_down_tx(mgr, txmsg);
|
||||||
|
|
||||||
ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
|
ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
|
||||||
@ -1499,11 +1511,12 @@ static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
|
|||||||
}
|
}
|
||||||
(*mgr->cbs->hotplug)(mgr);
|
(*mgr->cbs->hotplug)(mgr);
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
|
mstb->link_address_sent = false;
|
||||||
DRM_DEBUG_KMS("link address failed %d\n", ret);
|
DRM_DEBUG_KMS("link address failed %d\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
kfree(txmsg);
|
kfree(txmsg);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
|
static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
|
||||||
@ -1978,6 +1991,8 @@ void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr)
|
|||||||
drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
|
drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
|
||||||
DP_MST_EN | DP_UPSTREAM_IS_SRC);
|
DP_MST_EN | DP_UPSTREAM_IS_SRC);
|
||||||
mutex_unlock(&mgr->lock);
|
mutex_unlock(&mgr->lock);
|
||||||
|
flush_work(&mgr->work);
|
||||||
|
flush_work(&mgr->destroy_connector_work);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_dp_mst_topology_mgr_suspend);
|
EXPORT_SYMBOL(drm_dp_mst_topology_mgr_suspend);
|
||||||
|
|
||||||
@ -2263,10 +2278,10 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
|
|||||||
|
|
||||||
if (port->cached_edid)
|
if (port->cached_edid)
|
||||||
edid = drm_edid_duplicate(port->cached_edid);
|
edid = drm_edid_duplicate(port->cached_edid);
|
||||||
else
|
else {
|
||||||
edid = drm_get_edid(connector, &port->aux.ddc);
|
edid = drm_get_edid(connector, &port->aux.ddc);
|
||||||
|
drm_mode_connector_set_tile_property(connector);
|
||||||
drm_mode_connector_set_tile_property(connector);
|
}
|
||||||
drm_dp_put_port(port);
|
drm_dp_put_port(port);
|
||||||
return edid;
|
return edid;
|
||||||
}
|
}
|
||||||
@ -2671,7 +2686,7 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
|
|||||||
{
|
{
|
||||||
struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
|
struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
|
||||||
struct drm_dp_mst_port *port;
|
struct drm_dp_mst_port *port;
|
||||||
|
bool send_hotplug = false;
|
||||||
/*
|
/*
|
||||||
* Not a regular list traverse as we have to drop the destroy
|
* Not a regular list traverse as we have to drop the destroy
|
||||||
* connector lock before destroying the connector, to avoid AB->BA
|
* connector lock before destroying the connector, to avoid AB->BA
|
||||||
@ -2694,7 +2709,10 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
|
|||||||
if (!port->input && port->vcpi.vcpi > 0)
|
if (!port->input && port->vcpi.vcpi > 0)
|
||||||
drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
|
drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
|
||||||
kfree(port);
|
kfree(port);
|
||||||
|
send_hotplug = true;
|
||||||
}
|
}
|
||||||
|
if (send_hotplug)
|
||||||
|
(*mgr->cbs->hotplug)(mgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2747,6 +2765,7 @@ EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init);
|
|||||||
*/
|
*/
|
||||||
void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
|
void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
|
||||||
{
|
{
|
||||||
|
flush_work(&mgr->work);
|
||||||
flush_work(&mgr->destroy_connector_work);
|
flush_work(&mgr->destroy_connector_work);
|
||||||
mutex_lock(&mgr->payload_lock);
|
mutex_lock(&mgr->payload_lock);
|
||||||
kfree(mgr->payloads);
|
kfree(mgr->payloads);
|
||||||
|
@ -345,7 +345,11 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
|
|||||||
struct drm_crtc *crtc = mode_set->crtc;
|
struct drm_crtc *crtc = mode_set->crtc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (crtc->funcs->cursor_set) {
|
if (crtc->funcs->cursor_set2) {
|
||||||
|
ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0);
|
||||||
|
if (ret)
|
||||||
|
error = true;
|
||||||
|
} else if (crtc->funcs->cursor_set) {
|
||||||
ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
|
ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
error = true;
|
error = true;
|
||||||
|
@ -94,7 +94,18 @@ static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
|
#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
|
||||||
static void __drm_kms_helper_poll_enable(struct drm_device *dev)
|
/**
|
||||||
|
* drm_kms_helper_poll_enable_locked - re-enable output polling.
|
||||||
|
* @dev: drm_device
|
||||||
|
*
|
||||||
|
* This function re-enables the output polling work without
|
||||||
|
* locking the mode_config mutex.
|
||||||
|
*
|
||||||
|
* This is like drm_kms_helper_poll_enable() however it is to be
|
||||||
|
* called from a context where the mode_config mutex is locked
|
||||||
|
* already.
|
||||||
|
*/
|
||||||
|
void drm_kms_helper_poll_enable_locked(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
bool poll = false;
|
bool poll = false;
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
@ -113,6 +124,8 @@ static void __drm_kms_helper_poll_enable(struct drm_device *dev)
|
|||||||
if (poll)
|
if (poll)
|
||||||
schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
|
schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(drm_kms_helper_poll_enable_locked);
|
||||||
|
|
||||||
|
|
||||||
static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector,
|
static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector,
|
||||||
uint32_t maxX, uint32_t maxY, bool merge_type_bits)
|
uint32_t maxX, uint32_t maxY, bool merge_type_bits)
|
||||||
@ -174,7 +187,7 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
|
|||||||
|
|
||||||
/* Re-enable polling in case the global poll config changed. */
|
/* Re-enable polling in case the global poll config changed. */
|
||||||
if (drm_kms_helper_poll != dev->mode_config.poll_running)
|
if (drm_kms_helper_poll != dev->mode_config.poll_running)
|
||||||
__drm_kms_helper_poll_enable(dev);
|
drm_kms_helper_poll_enable_locked(dev);
|
||||||
|
|
||||||
dev->mode_config.poll_running = drm_kms_helper_poll;
|
dev->mode_config.poll_running = drm_kms_helper_poll;
|
||||||
|
|
||||||
@ -428,7 +441,7 @@ EXPORT_SYMBOL(drm_kms_helper_poll_disable);
|
|||||||
void drm_kms_helper_poll_enable(struct drm_device *dev)
|
void drm_kms_helper_poll_enable(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
mutex_lock(&dev->mode_config.mutex);
|
mutex_lock(&dev->mode_config.mutex);
|
||||||
__drm_kms_helper_poll_enable(dev);
|
drm_kms_helper_poll_enable_locked(dev);
|
||||||
mutex_unlock(&dev->mode_config.mutex);
|
mutex_unlock(&dev->mode_config.mutex);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_kms_helper_poll_enable);
|
EXPORT_SYMBOL(drm_kms_helper_poll_enable);
|
||||||
|
@ -37,7 +37,6 @@
|
|||||||
* DECON stands for Display and Enhancement controller.
|
* DECON stands for Display and Enhancement controller.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DECON_DEFAULT_FRAMERATE 60
|
|
||||||
#define MIN_FB_WIDTH_FOR_16WORD_BURST 128
|
#define MIN_FB_WIDTH_FOR_16WORD_BURST 128
|
||||||
|
|
||||||
#define WINDOWS_NR 2
|
#define WINDOWS_NR 2
|
||||||
@ -165,16 +164,6 @@ static u32 decon_calc_clkdiv(struct decon_context *ctx,
|
|||||||
return (clkdiv < 0x100) ? clkdiv : 0xff;
|
return (clkdiv < 0x100) ? clkdiv : 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool decon_mode_fixup(struct exynos_drm_crtc *crtc,
|
|
||||||
const struct drm_display_mode *mode,
|
|
||||||
struct drm_display_mode *adjusted_mode)
|
|
||||||
{
|
|
||||||
if (adjusted_mode->vrefresh == 0)
|
|
||||||
adjusted_mode->vrefresh = DECON_DEFAULT_FRAMERATE;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void decon_commit(struct exynos_drm_crtc *crtc)
|
static void decon_commit(struct exynos_drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct decon_context *ctx = crtc->ctx;
|
struct decon_context *ctx = crtc->ctx;
|
||||||
@ -637,7 +626,6 @@ static void decon_disable(struct exynos_drm_crtc *crtc)
|
|||||||
static const struct exynos_drm_crtc_ops decon_crtc_ops = {
|
static const struct exynos_drm_crtc_ops decon_crtc_ops = {
|
||||||
.enable = decon_enable,
|
.enable = decon_enable,
|
||||||
.disable = decon_disable,
|
.disable = decon_disable,
|
||||||
.mode_fixup = decon_mode_fixup,
|
|
||||||
.commit = decon_commit,
|
.commit = decon_commit,
|
||||||
.enable_vblank = decon_enable_vblank,
|
.enable_vblank = decon_enable_vblank,
|
||||||
.disable_vblank = decon_disable_vblank,
|
.disable_vblank = decon_disable_vblank,
|
||||||
|
@ -1383,28 +1383,6 @@ static int exynos_dp_remove(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
|
||||||
static int exynos_dp_suspend(struct device *dev)
|
|
||||||
{
|
|
||||||
struct exynos_dp_device *dp = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
exynos_dp_disable(&dp->encoder);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int exynos_dp_resume(struct device *dev)
|
|
||||||
{
|
|
||||||
struct exynos_dp_device *dp = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
exynos_dp_enable(&dp->encoder);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const struct dev_pm_ops exynos_dp_pm_ops = {
|
|
||||||
SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct of_device_id exynos_dp_match[] = {
|
static const struct of_device_id exynos_dp_match[] = {
|
||||||
{ .compatible = "samsung,exynos5-dp" },
|
{ .compatible = "samsung,exynos5-dp" },
|
||||||
{},
|
{},
|
||||||
@ -1417,7 +1395,6 @@ struct platform_driver dp_driver = {
|
|||||||
.driver = {
|
.driver = {
|
||||||
.name = "exynos-dp",
|
.name = "exynos-dp",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.pm = &exynos_dp_pm_ops,
|
|
||||||
.of_match_table = exynos_dp_match,
|
.of_match_table = exynos_dp_match,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -28,7 +28,6 @@ int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register);
|
|
||||||
|
|
||||||
int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
|
int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
|
||||||
{
|
{
|
||||||
@ -39,7 +38,6 @@ int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister);
|
|
||||||
|
|
||||||
int exynos_drm_device_subdrv_probe(struct drm_device *dev)
|
int exynos_drm_device_subdrv_probe(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
@ -69,7 +67,6 @@ int exynos_drm_device_subdrv_probe(struct drm_device *dev)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(exynos_drm_device_subdrv_probe);
|
|
||||||
|
|
||||||
int exynos_drm_device_subdrv_remove(struct drm_device *dev)
|
int exynos_drm_device_subdrv_remove(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
@ -87,7 +84,6 @@ int exynos_drm_device_subdrv_remove(struct drm_device *dev)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(exynos_drm_device_subdrv_remove);
|
|
||||||
|
|
||||||
int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
|
int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
|
||||||
{
|
{
|
||||||
@ -111,7 +107,6 @@ err:
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(exynos_drm_subdrv_open);
|
|
||||||
|
|
||||||
void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file)
|
void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file)
|
||||||
{
|
{
|
||||||
@ -122,4 +117,3 @@ void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file)
|
|||||||
subdrv->close(dev, subdrv->dev, file);
|
subdrv->close(dev, subdrv->dev, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close);
|
|
||||||
|
@ -41,20 +41,6 @@ static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
|
|||||||
exynos_crtc->ops->disable(exynos_crtc);
|
exynos_crtc->ops->disable(exynos_crtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
|
|
||||||
const struct drm_display_mode *mode,
|
|
||||||
struct drm_display_mode *adjusted_mode)
|
|
||||||
{
|
|
||||||
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
|
|
||||||
|
|
||||||
if (exynos_crtc->ops->mode_fixup)
|
|
||||||
return exynos_crtc->ops->mode_fixup(exynos_crtc, mode,
|
|
||||||
adjusted_mode);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
exynos_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
exynos_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
@ -99,7 +85,6 @@ static void exynos_crtc_atomic_flush(struct drm_crtc *crtc,
|
|||||||
static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
|
static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
|
||||||
.enable = exynos_drm_crtc_enable,
|
.enable = exynos_drm_crtc_enable,
|
||||||
.disable = exynos_drm_crtc_disable,
|
.disable = exynos_drm_crtc_disable,
|
||||||
.mode_fixup = exynos_drm_crtc_mode_fixup,
|
|
||||||
.mode_set_nofb = exynos_drm_crtc_mode_set_nofb,
|
.mode_set_nofb = exynos_drm_crtc_mode_set_nofb,
|
||||||
.atomic_begin = exynos_crtc_atomic_begin,
|
.atomic_begin = exynos_crtc_atomic_begin,
|
||||||
.atomic_flush = exynos_crtc_atomic_flush,
|
.atomic_flush = exynos_crtc_atomic_flush,
|
||||||
|
@ -304,6 +304,7 @@ int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state)
|
static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state)
|
||||||
{
|
{
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
@ -340,6 +341,7 @@ static int exynos_drm_resume(struct drm_device *dev)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
|
static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
|
||||||
{
|
{
|
||||||
|
@ -82,7 +82,6 @@ struct exynos_drm_plane {
|
|||||||
*
|
*
|
||||||
* @enable: enable the device
|
* @enable: enable the device
|
||||||
* @disable: disable the device
|
* @disable: disable the device
|
||||||
* @mode_fixup: fix mode data before applying it
|
|
||||||
* @commit: set current hw specific display mode to hw.
|
* @commit: set current hw specific display mode to hw.
|
||||||
* @enable_vblank: specific driver callback for enabling vblank interrupt.
|
* @enable_vblank: specific driver callback for enabling vblank interrupt.
|
||||||
* @disable_vblank: specific driver callback for disabling vblank interrupt.
|
* @disable_vblank: specific driver callback for disabling vblank interrupt.
|
||||||
@ -103,9 +102,6 @@ struct exynos_drm_crtc;
|
|||||||
struct exynos_drm_crtc_ops {
|
struct exynos_drm_crtc_ops {
|
||||||
void (*enable)(struct exynos_drm_crtc *crtc);
|
void (*enable)(struct exynos_drm_crtc *crtc);
|
||||||
void (*disable)(struct exynos_drm_crtc *crtc);
|
void (*disable)(struct exynos_drm_crtc *crtc);
|
||||||
bool (*mode_fixup)(struct exynos_drm_crtc *crtc,
|
|
||||||
const struct drm_display_mode *mode,
|
|
||||||
struct drm_display_mode *adjusted_mode);
|
|
||||||
void (*commit)(struct exynos_drm_crtc *crtc);
|
void (*commit)(struct exynos_drm_crtc *crtc);
|
||||||
int (*enable_vblank)(struct exynos_drm_crtc *crtc);
|
int (*enable_vblank)(struct exynos_drm_crtc *crtc);
|
||||||
void (*disable_vblank)(struct exynos_drm_crtc *crtc);
|
void (*disable_vblank)(struct exynos_drm_crtc *crtc);
|
||||||
|
@ -1206,23 +1206,6 @@ static struct exynos_drm_ipp_ops fimc_dst_ops = {
|
|||||||
.set_addr = fimc_dst_set_addr,
|
.set_addr = fimc_dst_set_addr,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
|
|
||||||
{
|
|
||||||
DRM_DEBUG_KMS("enable[%d]\n", enable);
|
|
||||||
|
|
||||||
if (enable) {
|
|
||||||
clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
|
|
||||||
clk_prepare_enable(ctx->clocks[FIMC_CLK_WB_A]);
|
|
||||||
ctx->suspended = false;
|
|
||||||
} else {
|
|
||||||
clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]);
|
|
||||||
clk_disable_unprepare(ctx->clocks[FIMC_CLK_WB_A]);
|
|
||||||
ctx->suspended = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
|
static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct fimc_context *ctx = dev_id;
|
struct fimc_context *ctx = dev_id;
|
||||||
@ -1780,6 +1763,24 @@ static int fimc_remove(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
|
||||||
|
{
|
||||||
|
DRM_DEBUG_KMS("enable[%d]\n", enable);
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
|
||||||
|
clk_prepare_enable(ctx->clocks[FIMC_CLK_WB_A]);
|
||||||
|
ctx->suspended = false;
|
||||||
|
} else {
|
||||||
|
clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]);
|
||||||
|
clk_disable_unprepare(ctx->clocks[FIMC_CLK_WB_A]);
|
||||||
|
ctx->suspended = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
static int fimc_suspend(struct device *dev)
|
static int fimc_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
@ -1806,7 +1807,6 @@ static int fimc_resume(struct device *dev)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
|
||||||
static int fimc_runtime_suspend(struct device *dev)
|
static int fimc_runtime_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct fimc_context *ctx = get_fimc_context(dev);
|
struct fimc_context *ctx = get_fimc_context(dev);
|
||||||
|
@ -41,7 +41,6 @@
|
|||||||
* CPU Interface.
|
* CPU Interface.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define FIMD_DEFAULT_FRAMERATE 60
|
|
||||||
#define MIN_FB_WIDTH_FOR_16WORD_BURST 128
|
#define MIN_FB_WIDTH_FOR_16WORD_BURST 128
|
||||||
|
|
||||||
/* position control register for hardware window 0, 2 ~ 4.*/
|
/* position control register for hardware window 0, 2 ~ 4.*/
|
||||||
@ -377,16 +376,6 @@ static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
|
|||||||
return (clkdiv < 0x100) ? clkdiv : 0xff;
|
return (clkdiv < 0x100) ? clkdiv : 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool fimd_mode_fixup(struct exynos_drm_crtc *crtc,
|
|
||||||
const struct drm_display_mode *mode,
|
|
||||||
struct drm_display_mode *adjusted_mode)
|
|
||||||
{
|
|
||||||
if (adjusted_mode->vrefresh == 0)
|
|
||||||
adjusted_mode->vrefresh = FIMD_DEFAULT_FRAMERATE;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fimd_commit(struct exynos_drm_crtc *crtc)
|
static void fimd_commit(struct exynos_drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct fimd_context *ctx = crtc->ctx;
|
struct fimd_context *ctx = crtc->ctx;
|
||||||
@ -882,13 +871,12 @@ static void fimd_dp_clock_enable(struct exynos_drm_crtc *crtc, bool enable)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE;
|
val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE;
|
||||||
writel(DP_MIE_CLK_DP_ENABLE, ctx->regs + DP_MIE_CLKCON);
|
writel(val, ctx->regs + DP_MIE_CLKCON);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct exynos_drm_crtc_ops fimd_crtc_ops = {
|
static const struct exynos_drm_crtc_ops fimd_crtc_ops = {
|
||||||
.enable = fimd_enable,
|
.enable = fimd_enable,
|
||||||
.disable = fimd_disable,
|
.disable = fimd_disable,
|
||||||
.mode_fixup = fimd_mode_fixup,
|
|
||||||
.commit = fimd_commit,
|
.commit = fimd_commit,
|
||||||
.enable_vblank = fimd_enable_vblank,
|
.enable_vblank = fimd_enable_vblank,
|
||||||
.disable_vblank = fimd_disable_vblank,
|
.disable_vblank = fimd_disable_vblank,
|
||||||
|
@ -1059,7 +1059,6 @@ int exynos_g2d_get_ver_ioctl(struct drm_device *drm_dev, void *data,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(exynos_g2d_get_ver_ioctl);
|
|
||||||
|
|
||||||
int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
|
int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
|
||||||
struct drm_file *file)
|
struct drm_file *file)
|
||||||
@ -1230,7 +1229,6 @@ err:
|
|||||||
g2d_put_cmdlist(g2d, node);
|
g2d_put_cmdlist(g2d, node);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(exynos_g2d_set_cmdlist_ioctl);
|
|
||||||
|
|
||||||
int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
|
int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
|
||||||
struct drm_file *file)
|
struct drm_file *file)
|
||||||
@ -1293,7 +1291,6 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
|
|||||||
out:
|
out:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(exynos_g2d_exec_ioctl);
|
|
||||||
|
|
||||||
static int g2d_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
|
static int g2d_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
|
||||||
{
|
{
|
||||||
|
@ -56,39 +56,35 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem_obj *obj)
|
|||||||
nr_pages = obj->size >> PAGE_SHIFT;
|
nr_pages = obj->size >> PAGE_SHIFT;
|
||||||
|
|
||||||
if (!is_drm_iommu_supported(dev)) {
|
if (!is_drm_iommu_supported(dev)) {
|
||||||
dma_addr_t start_addr;
|
|
||||||
unsigned int i = 0;
|
|
||||||
|
|
||||||
obj->pages = drm_calloc_large(nr_pages, sizeof(struct page *));
|
obj->pages = drm_calloc_large(nr_pages, sizeof(struct page *));
|
||||||
if (!obj->pages) {
|
if (!obj->pages) {
|
||||||
DRM_ERROR("failed to allocate pages.\n");
|
DRM_ERROR("failed to allocate pages.\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
obj->cookie = dma_alloc_attrs(dev->dev,
|
obj->cookie = dma_alloc_attrs(dev->dev, obj->size, &obj->dma_addr,
|
||||||
obj->size,
|
GFP_KERNEL, &obj->dma_attrs);
|
||||||
&obj->dma_addr, GFP_KERNEL,
|
if (!obj->cookie) {
|
||||||
&obj->dma_attrs);
|
DRM_ERROR("failed to allocate buffer.\n");
|
||||||
if (!obj->cookie) {
|
if (obj->pages)
|
||||||
DRM_ERROR("failed to allocate buffer.\n");
|
|
||||||
drm_free_large(obj->pages);
|
drm_free_large(obj->pages);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (obj->pages) {
|
||||||
|
dma_addr_t start_addr;
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
start_addr = obj->dma_addr;
|
start_addr = obj->dma_addr;
|
||||||
while (i < nr_pages) {
|
while (i < nr_pages) {
|
||||||
obj->pages[i] = phys_to_page(start_addr);
|
obj->pages[i] = pfn_to_page(dma_to_pfn(dev->dev,
|
||||||
|
start_addr));
|
||||||
start_addr += PAGE_SIZE;
|
start_addr += PAGE_SIZE;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
obj->pages = dma_alloc_attrs(dev->dev, obj->size,
|
obj->pages = obj->cookie;
|
||||||
&obj->dma_addr, GFP_KERNEL,
|
|
||||||
&obj->dma_attrs);
|
|
||||||
if (!obj->pages) {
|
|
||||||
DRM_ERROR("failed to allocate buffer.\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
|
DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
|
||||||
@ -110,15 +106,11 @@ static void exynos_drm_free_buf(struct exynos_drm_gem_obj *obj)
|
|||||||
DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
|
DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
|
||||||
(unsigned long)obj->dma_addr, obj->size);
|
(unsigned long)obj->dma_addr, obj->size);
|
||||||
|
|
||||||
if (!is_drm_iommu_supported(dev)) {
|
dma_free_attrs(dev->dev, obj->size, obj->cookie,
|
||||||
dma_free_attrs(dev->dev, obj->size, obj->cookie,
|
(dma_addr_t)obj->dma_addr, &obj->dma_attrs);
|
||||||
(dma_addr_t)obj->dma_addr, &obj->dma_attrs);
|
|
||||||
drm_free_large(obj->pages);
|
|
||||||
} else
|
|
||||||
dma_free_attrs(dev->dev, obj->size, obj->pages,
|
|
||||||
(dma_addr_t)obj->dma_addr, &obj->dma_attrs);
|
|
||||||
|
|
||||||
obj->dma_addr = (dma_addr_t)NULL;
|
if (!is_drm_iommu_supported(dev))
|
||||||
|
drm_free_large(obj->pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
|
static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
|
||||||
@ -156,18 +148,14 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
|
|||||||
* once dmabuf's refcount becomes 0.
|
* once dmabuf's refcount becomes 0.
|
||||||
*/
|
*/
|
||||||
if (obj->import_attach)
|
if (obj->import_attach)
|
||||||
goto out;
|
drm_prime_gem_destroy(obj, exynos_gem_obj->sgt);
|
||||||
|
else
|
||||||
exynos_drm_free_buf(exynos_gem_obj);
|
exynos_drm_free_buf(exynos_gem_obj);
|
||||||
|
|
||||||
out:
|
|
||||||
drm_gem_free_mmap_offset(obj);
|
|
||||||
|
|
||||||
/* release file pointer to gem object. */
|
/* release file pointer to gem object. */
|
||||||
drm_gem_object_release(obj);
|
drm_gem_object_release(obj);
|
||||||
|
|
||||||
kfree(exynos_gem_obj);
|
kfree(exynos_gem_obj);
|
||||||
exynos_gem_obj = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
|
unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
|
||||||
@ -190,8 +178,7 @@ unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
|
|||||||
return exynos_gem_obj->size;
|
return exynos_gem_obj->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
|
||||||
struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
|
|
||||||
unsigned long size)
|
unsigned long size)
|
||||||
{
|
{
|
||||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||||
@ -212,6 +199,13 @@ struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
|
|||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = drm_gem_create_mmap_offset(obj);
|
||||||
|
if (ret < 0) {
|
||||||
|
drm_gem_object_release(obj);
|
||||||
|
kfree(exynos_gem_obj);
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
}
|
||||||
|
|
||||||
DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
|
DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
|
||||||
|
|
||||||
return exynos_gem_obj;
|
return exynos_gem_obj;
|
||||||
@ -313,7 +307,7 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
|
|||||||
drm_gem_object_unreference_unlocked(obj);
|
drm_gem_object_unreference_unlocked(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem_obj *exynos_gem_obj,
|
static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem_obj *exynos_gem_obj,
|
||||||
struct vm_area_struct *vma)
|
struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
struct drm_device *drm_dev = exynos_gem_obj->base.dev;
|
struct drm_device *drm_dev = exynos_gem_obj->base.dev;
|
||||||
@ -342,7 +336,8 @@ int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem_obj *exynos_gem_obj,
|
|||||||
|
|
||||||
int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
|
int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file_priv)
|
struct drm_file *file_priv)
|
||||||
{ struct exynos_drm_gem_obj *exynos_gem_obj;
|
{
|
||||||
|
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||||
struct drm_exynos_gem_info *args = data;
|
struct drm_exynos_gem_info *args = data;
|
||||||
struct drm_gem_object *obj;
|
struct drm_gem_object *obj;
|
||||||
|
|
||||||
@ -402,6 +397,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
|
|||||||
struct drm_mode_create_dumb *args)
|
struct drm_mode_create_dumb *args)
|
||||||
{
|
{
|
||||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||||
|
unsigned int flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -413,16 +409,12 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
|
|||||||
args->pitch = args->width * ((args->bpp + 7) / 8);
|
args->pitch = args->width * ((args->bpp + 7) / 8);
|
||||||
args->size = args->pitch * args->height;
|
args->size = args->pitch * args->height;
|
||||||
|
|
||||||
if (is_drm_iommu_supported(dev)) {
|
if (is_drm_iommu_supported(dev))
|
||||||
exynos_gem_obj = exynos_drm_gem_create(dev,
|
flags = EXYNOS_BO_NONCONTIG | EXYNOS_BO_WC;
|
||||||
EXYNOS_BO_NONCONTIG | EXYNOS_BO_WC,
|
else
|
||||||
args->size);
|
flags = EXYNOS_BO_CONTIG | EXYNOS_BO_WC;
|
||||||
} else {
|
|
||||||
exynos_gem_obj = exynos_drm_gem_create(dev,
|
|
||||||
EXYNOS_BO_CONTIG | EXYNOS_BO_WC,
|
|
||||||
args->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
exynos_gem_obj = exynos_drm_gem_create(dev, flags, args->size);
|
||||||
if (IS_ERR(exynos_gem_obj)) {
|
if (IS_ERR(exynos_gem_obj)) {
|
||||||
dev_warn(dev->dev, "FB allocation failed.\n");
|
dev_warn(dev->dev, "FB allocation failed.\n");
|
||||||
return PTR_ERR(exynos_gem_obj);
|
return PTR_ERR(exynos_gem_obj);
|
||||||
@ -460,14 +452,9 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
|
|||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = drm_gem_create_mmap_offset(obj);
|
|
||||||
if (ret)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
*offset = drm_vma_node_offset_addr(&obj->vma_node);
|
*offset = drm_vma_node_offset_addr(&obj->vma_node);
|
||||||
DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
|
DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
|
||||||
|
|
||||||
out:
|
|
||||||
drm_gem_object_unreference(obj);
|
drm_gem_object_unreference(obj);
|
||||||
unlock:
|
unlock:
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
@ -543,7 +530,6 @@ int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||||||
|
|
||||||
err_close_vm:
|
err_close_vm:
|
||||||
drm_gem_vm_close(vma);
|
drm_gem_vm_close(vma);
|
||||||
drm_gem_free_mmap_offset(obj);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -588,6 +574,8 @@ exynos_drm_gem_prime_import_sg_table(struct drm_device *dev,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_free_large;
|
goto err_free_large;
|
||||||
|
|
||||||
|
exynos_gem_obj->sgt = sgt;
|
||||||
|
|
||||||
if (sgt->nents == 1) {
|
if (sgt->nents == 1) {
|
||||||
/* always physically continuous memory if sgt->nents is 1. */
|
/* always physically continuous memory if sgt->nents is 1. */
|
||||||
exynos_gem_obj->flags |= EXYNOS_BO_CONTIG;
|
exynos_gem_obj->flags |= EXYNOS_BO_CONTIG;
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
* - this address could be physical address without IOMMU and
|
* - this address could be physical address without IOMMU and
|
||||||
* device address with IOMMU.
|
* device address with IOMMU.
|
||||||
* @pages: Array of backing pages.
|
* @pages: Array of backing pages.
|
||||||
|
* @sgt: Imported sg_table.
|
||||||
*
|
*
|
||||||
* P.S. this object would be transferred to user as kms_bo.handle so
|
* P.S. this object would be transferred to user as kms_bo.handle so
|
||||||
* user can access the buffer through kms_bo.handle.
|
* user can access the buffer through kms_bo.handle.
|
||||||
@ -52,6 +53,7 @@ struct exynos_drm_gem_obj {
|
|||||||
dma_addr_t dma_addr;
|
dma_addr_t dma_addr;
|
||||||
struct dma_attrs dma_attrs;
|
struct dma_attrs dma_attrs;
|
||||||
struct page **pages;
|
struct page **pages;
|
||||||
|
struct sg_table *sgt;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
|
struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
|
||||||
@ -59,10 +61,6 @@ struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
|
|||||||
/* destroy a buffer with gem object */
|
/* destroy a buffer with gem object */
|
||||||
void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj);
|
void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj);
|
||||||
|
|
||||||
/* create a private gem object and initialize it. */
|
|
||||||
struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
|
|
||||||
unsigned long size);
|
|
||||||
|
|
||||||
/* create a new buffer with gem object */
|
/* create a new buffer with gem object */
|
||||||
struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
|
struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
|
||||||
unsigned int flags,
|
unsigned int flags,
|
||||||
|
@ -786,6 +786,7 @@ static int rotator_remove(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
static int rotator_clk_crtl(struct rot_context *rot, bool enable)
|
static int rotator_clk_crtl(struct rot_context *rot, bool enable)
|
||||||
{
|
{
|
||||||
if (enable) {
|
if (enable) {
|
||||||
@ -822,7 +823,6 @@ static int rotator_resume(struct device *dev)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
|
||||||
static int rotator_runtime_suspend(struct device *dev)
|
static int rotator_runtime_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct rot_context *rot = dev_get_drvdata(dev);
|
struct rot_context *rot = dev_get_drvdata(dev);
|
||||||
|
@ -462,11 +462,17 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
|
|||||||
drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0);
|
drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0);
|
||||||
|
|
||||||
drm_mode_connector_set_path_property(connector, pathprop);
|
drm_mode_connector_set_path_property(connector, pathprop);
|
||||||
|
return connector;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void intel_dp_register_mst_connector(struct drm_connector *connector)
|
||||||
|
{
|
||||||
|
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||||
|
struct drm_device *dev = connector->dev;
|
||||||
drm_modeset_lock_all(dev);
|
drm_modeset_lock_all(dev);
|
||||||
intel_connector_add_to_fbdev(intel_connector);
|
intel_connector_add_to_fbdev(intel_connector);
|
||||||
drm_modeset_unlock_all(dev);
|
drm_modeset_unlock_all(dev);
|
||||||
drm_connector_register(&intel_connector->base);
|
drm_connector_register(&intel_connector->base);
|
||||||
return connector;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
||||||
@ -512,6 +518,7 @@ static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
|
|||||||
|
|
||||||
static struct drm_dp_mst_topology_cbs mst_cbs = {
|
static struct drm_dp_mst_topology_cbs mst_cbs = {
|
||||||
.add_connector = intel_dp_add_mst_connector,
|
.add_connector = intel_dp_add_mst_connector,
|
||||||
|
.register_connector = intel_dp_register_mst_connector,
|
||||||
.destroy_connector = intel_dp_destroy_mst_connector,
|
.destroy_connector = intel_dp_destroy_mst_connector,
|
||||||
.hotplug = intel_dp_mst_hotplug,
|
.hotplug = intel_dp_mst_hotplug,
|
||||||
};
|
};
|
||||||
|
@ -180,7 +180,7 @@ static void intel_hpd_irq_storm_disable(struct drm_i915_private *dev_priv)
|
|||||||
|
|
||||||
/* Enable polling and queue hotplug re-enabling. */
|
/* Enable polling and queue hotplug re-enabling. */
|
||||||
if (hpd_disabled) {
|
if (hpd_disabled) {
|
||||||
drm_kms_helper_poll_enable(dev);
|
drm_kms_helper_poll_enable_locked(dev);
|
||||||
mod_delayed_work(system_wq, &dev_priv->hotplug.reenable_work,
|
mod_delayed_work(system_wq, &dev_priv->hotplug.reenable_work,
|
||||||
msecs_to_jiffies(HPD_STORM_REENABLE_DELAY));
|
msecs_to_jiffies(HPD_STORM_REENABLE_DELAY));
|
||||||
}
|
}
|
||||||
|
@ -484,18 +484,18 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring)
|
|||||||
status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring));
|
status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring));
|
||||||
|
|
||||||
read_pointer = ring->next_context_status_buffer;
|
read_pointer = ring->next_context_status_buffer;
|
||||||
write_pointer = status_pointer & 0x07;
|
write_pointer = status_pointer & GEN8_CSB_PTR_MASK;
|
||||||
if (read_pointer > write_pointer)
|
if (read_pointer > write_pointer)
|
||||||
write_pointer += 6;
|
write_pointer += GEN8_CSB_ENTRIES;
|
||||||
|
|
||||||
spin_lock(&ring->execlist_lock);
|
spin_lock(&ring->execlist_lock);
|
||||||
|
|
||||||
while (read_pointer < write_pointer) {
|
while (read_pointer < write_pointer) {
|
||||||
read_pointer++;
|
read_pointer++;
|
||||||
status = I915_READ(RING_CONTEXT_STATUS_BUF(ring) +
|
status = I915_READ(RING_CONTEXT_STATUS_BUF(ring) +
|
||||||
(read_pointer % 6) * 8);
|
(read_pointer % GEN8_CSB_ENTRIES) * 8);
|
||||||
status_id = I915_READ(RING_CONTEXT_STATUS_BUF(ring) +
|
status_id = I915_READ(RING_CONTEXT_STATUS_BUF(ring) +
|
||||||
(read_pointer % 6) * 8 + 4);
|
(read_pointer % GEN8_CSB_ENTRIES) * 8 + 4);
|
||||||
|
|
||||||
if (status & GEN8_CTX_STATUS_IDLE_ACTIVE)
|
if (status & GEN8_CTX_STATUS_IDLE_ACTIVE)
|
||||||
continue;
|
continue;
|
||||||
@ -521,10 +521,12 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring)
|
|||||||
spin_unlock(&ring->execlist_lock);
|
spin_unlock(&ring->execlist_lock);
|
||||||
|
|
||||||
WARN(submit_contexts > 2, "More than two context complete events?\n");
|
WARN(submit_contexts > 2, "More than two context complete events?\n");
|
||||||
ring->next_context_status_buffer = write_pointer % 6;
|
ring->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES;
|
||||||
|
|
||||||
I915_WRITE(RING_CONTEXT_STATUS_PTR(ring),
|
I915_WRITE(RING_CONTEXT_STATUS_PTR(ring),
|
||||||
_MASKED_FIELD(0x07 << 8, ((u32)ring->next_context_status_buffer & 0x07) << 8));
|
_MASKED_FIELD(GEN8_CSB_PTR_MASK << 8,
|
||||||
|
((u32)ring->next_context_status_buffer &
|
||||||
|
GEN8_CSB_PTR_MASK) << 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int execlists_context_queue(struct drm_i915_gem_request *request)
|
static int execlists_context_queue(struct drm_i915_gem_request *request)
|
||||||
@ -1422,6 +1424,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
|
|||||||
{
|
{
|
||||||
struct drm_device *dev = ring->dev;
|
struct drm_device *dev = ring->dev;
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
|
u8 next_context_status_buffer_hw;
|
||||||
|
|
||||||
I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask));
|
I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask));
|
||||||
I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff);
|
I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff);
|
||||||
@ -1436,7 +1439,29 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
|
|||||||
_MASKED_BIT_DISABLE(GFX_REPLAY_MODE) |
|
_MASKED_BIT_DISABLE(GFX_REPLAY_MODE) |
|
||||||
_MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
|
_MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
|
||||||
POSTING_READ(RING_MODE_GEN7(ring));
|
POSTING_READ(RING_MODE_GEN7(ring));
|
||||||
ring->next_context_status_buffer = 0;
|
|
||||||
|
/*
|
||||||
|
* Instead of resetting the Context Status Buffer (CSB) read pointer to
|
||||||
|
* zero, we need to read the write pointer from hardware and use its
|
||||||
|
* value because "this register is power context save restored".
|
||||||
|
* Effectively, these states have been observed:
|
||||||
|
*
|
||||||
|
* | Suspend-to-idle (freeze) | Suspend-to-RAM (mem) |
|
||||||
|
* BDW | CSB regs not reset | CSB regs reset |
|
||||||
|
* CHT | CSB regs not reset | CSB regs not reset |
|
||||||
|
*/
|
||||||
|
next_context_status_buffer_hw = (I915_READ(RING_CONTEXT_STATUS_PTR(ring))
|
||||||
|
& GEN8_CSB_PTR_MASK);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the CSB registers are reset (also after power-up / gpu reset),
|
||||||
|
* CSB write pointer is set to all 1's, which is not valid, use '5' in
|
||||||
|
* this special case, so the first element read is CSB[0].
|
||||||
|
*/
|
||||||
|
if (next_context_status_buffer_hw == GEN8_CSB_PTR_MASK)
|
||||||
|
next_context_status_buffer_hw = (GEN8_CSB_ENTRIES - 1);
|
||||||
|
|
||||||
|
ring->next_context_status_buffer = next_context_status_buffer_hw;
|
||||||
DRM_DEBUG_DRIVER("Execlists enabled for %s\n", ring->name);
|
DRM_DEBUG_DRIVER("Execlists enabled for %s\n", ring->name);
|
||||||
|
|
||||||
memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
|
memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#define _INTEL_LRC_H_
|
#define _INTEL_LRC_H_
|
||||||
|
|
||||||
#define GEN8_LR_CONTEXT_ALIGN 4096
|
#define GEN8_LR_CONTEXT_ALIGN 4096
|
||||||
|
#define GEN8_CSB_ENTRIES 6
|
||||||
|
#define GEN8_CSB_PTR_MASK 0x07
|
||||||
|
|
||||||
/* Execlists regs */
|
/* Execlists regs */
|
||||||
#define RING_ELSP(ring) ((ring)->mmio_base+0x230)
|
#define RING_ELSP(ring) ((ring)->mmio_base+0x230)
|
||||||
|
@ -246,7 +246,8 @@ static void skl_power_well_post_enable(struct drm_i915_private *dev_priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (power_well->data == SKL_DISP_PW_1) {
|
if (power_well->data == SKL_DISP_PW_1) {
|
||||||
intel_prepare_ddi(dev);
|
if (!dev_priv->power_domains.initializing)
|
||||||
|
intel_prepare_ddi(dev);
|
||||||
gen8_irq_power_well_post_enable(dev_priv, 1 << PIPE_A);
|
gen8_irq_power_well_post_enable(dev_priv, 1 << PIPE_A);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -618,7 +618,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
|
|||||||
adjusted_mode->hdisplay,
|
adjusted_mode->hdisplay,
|
||||||
adjusted_mode->vdisplay);
|
adjusted_mode->vdisplay);
|
||||||
|
|
||||||
if (qcrtc->index == 0)
|
if (bo->is_primary == false)
|
||||||
recreate_primary = true;
|
recreate_primary = true;
|
||||||
|
|
||||||
if (bo->surf.stride * bo->surf.height > qdev->vram_size) {
|
if (bo->surf.stride * bo->surf.height > qdev->vram_size) {
|
||||||
|
@ -1624,8 +1624,9 @@ radeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode)
|
|||||||
} else
|
} else
|
||||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||||
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
|
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
|
||||||
args.ucAction = ATOM_LCD_BLON;
|
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
||||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
|
||||||
|
atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DRM_MODE_DPMS_STANDBY:
|
case DRM_MODE_DPMS_STANDBY:
|
||||||
@ -1706,8 +1707,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
|
|||||||
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
|
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
|
||||||
}
|
}
|
||||||
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
|
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
|
||||||
atombios_dig_transmitter_setup(encoder,
|
atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
|
||||||
ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
|
|
||||||
if (ext_encoder)
|
if (ext_encoder)
|
||||||
atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
|
atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
|
||||||
break;
|
break;
|
||||||
|
@ -265,7 +265,6 @@ static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topol
|
|||||||
{
|
{
|
||||||
struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
|
struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
|
||||||
struct drm_device *dev = master->base.dev;
|
struct drm_device *dev = master->base.dev;
|
||||||
struct radeon_device *rdev = dev->dev_private;
|
|
||||||
struct radeon_connector *radeon_connector;
|
struct radeon_connector *radeon_connector;
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
|
|
||||||
@ -286,12 +285,19 @@ static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topol
|
|||||||
drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0);
|
drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0);
|
||||||
drm_mode_connector_set_path_property(connector, pathprop);
|
drm_mode_connector_set_path_property(connector, pathprop);
|
||||||
|
|
||||||
|
return connector;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radeon_dp_register_mst_connector(struct drm_connector *connector)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = connector->dev;
|
||||||
|
struct radeon_device *rdev = dev->dev_private;
|
||||||
|
|
||||||
drm_modeset_lock_all(dev);
|
drm_modeset_lock_all(dev);
|
||||||
radeon_fb_add_connector(rdev, connector);
|
radeon_fb_add_connector(rdev, connector);
|
||||||
drm_modeset_unlock_all(dev);
|
drm_modeset_unlock_all(dev);
|
||||||
|
|
||||||
drm_connector_register(connector);
|
drm_connector_register(connector);
|
||||||
return connector;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void radeon_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
static void radeon_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
||||||
@ -324,6 +330,7 @@ static void radeon_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
|
|||||||
|
|
||||||
struct drm_dp_mst_topology_cbs mst_cbs = {
|
struct drm_dp_mst_topology_cbs mst_cbs = {
|
||||||
.add_connector = radeon_dp_add_mst_connector,
|
.add_connector = radeon_dp_add_mst_connector,
|
||||||
|
.register_connector = radeon_dp_register_mst_connector,
|
||||||
.destroy_connector = radeon_dp_destroy_mst_connector,
|
.destroy_connector = radeon_dp_destroy_mst_connector,
|
||||||
.hotplug = radeon_dp_mst_hotplug,
|
.hotplug = radeon_dp_mst_hotplug,
|
||||||
};
|
};
|
||||||
|
@ -48,40 +48,10 @@ struct radeon_fbdev {
|
|||||||
struct radeon_device *rdev;
|
struct radeon_device *rdev;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* radeon_fb_helper_set_par - Hide cursor on CRTCs used by fbdev.
|
|
||||||
*
|
|
||||||
* @info: fbdev info
|
|
||||||
*
|
|
||||||
* This function hides the cursor on all CRTCs used by fbdev.
|
|
||||||
*/
|
|
||||||
static int radeon_fb_helper_set_par(struct fb_info *info)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = drm_fb_helper_set_par(info);
|
|
||||||
|
|
||||||
/* XXX: with universal plane support fbdev will automatically disable
|
|
||||||
* all non-primary planes (including the cursor)
|
|
||||||
*/
|
|
||||||
if (ret == 0) {
|
|
||||||
struct drm_fb_helper *fb_helper = info->par;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
|
||||||
struct drm_crtc *crtc = fb_helper->crtc_info[i].mode_set.crtc;
|
|
||||||
|
|
||||||
radeon_crtc_cursor_set2(crtc, NULL, 0, 0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct fb_ops radeonfb_ops = {
|
static struct fb_ops radeonfb_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.fb_check_var = drm_fb_helper_check_var,
|
.fb_check_var = drm_fb_helper_check_var,
|
||||||
.fb_set_par = radeon_fb_helper_set_par,
|
.fb_set_par = drm_fb_helper_set_par,
|
||||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||||
|
@ -681,6 +681,14 @@ static bool vmw_cmdbuf_try_alloc(struct vmw_cmdbuf_man *man,
|
|||||||
0, 0,
|
0, 0,
|
||||||
DRM_MM_SEARCH_DEFAULT,
|
DRM_MM_SEARCH_DEFAULT,
|
||||||
DRM_MM_CREATE_DEFAULT);
|
DRM_MM_CREATE_DEFAULT);
|
||||||
|
if (ret) {
|
||||||
|
(void) vmw_cmdbuf_man_process(man);
|
||||||
|
ret = drm_mm_insert_node_generic(&man->mm, info->node,
|
||||||
|
info->page_size, 0, 0,
|
||||||
|
DRM_MM_SEARCH_DEFAULT,
|
||||||
|
DRM_MM_CREATE_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
spin_unlock_bh(&man->lock);
|
spin_unlock_bh(&man->lock);
|
||||||
info->done = !ret;
|
info->done = !ret;
|
||||||
|
|
||||||
|
@ -240,5 +240,6 @@ extern void drm_kms_helper_hotplug_event(struct drm_device *dev);
|
|||||||
|
|
||||||
extern void drm_kms_helper_poll_disable(struct drm_device *dev);
|
extern void drm_kms_helper_poll_disable(struct drm_device *dev);
|
||||||
extern void drm_kms_helper_poll_enable(struct drm_device *dev);
|
extern void drm_kms_helper_poll_enable(struct drm_device *dev);
|
||||||
|
extern void drm_kms_helper_poll_enable_locked(struct drm_device *dev);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -568,6 +568,10 @@
|
|||||||
#define MODE_I2C_READ 4
|
#define MODE_I2C_READ 4
|
||||||
#define MODE_I2C_STOP 8
|
#define MODE_I2C_STOP 8
|
||||||
|
|
||||||
|
/* DP 1.2 MST PORTs - Section 2.5.1 v1.2a spec */
|
||||||
|
#define DP_MST_PHYSICAL_PORT_0 0
|
||||||
|
#define DP_MST_LOGICAL_PORT_0 8
|
||||||
|
|
||||||
#define DP_LINK_STATUS_SIZE 6
|
#define DP_LINK_STATUS_SIZE 6
|
||||||
bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE],
|
bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE],
|
||||||
int lane_count);
|
int lane_count);
|
||||||
|
@ -374,6 +374,7 @@ struct drm_dp_mst_topology_mgr;
|
|||||||
struct drm_dp_mst_topology_cbs {
|
struct drm_dp_mst_topology_cbs {
|
||||||
/* create a connector for a port */
|
/* create a connector for a port */
|
||||||
struct drm_connector *(*add_connector)(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, const char *path);
|
struct drm_connector *(*add_connector)(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, const char *path);
|
||||||
|
void (*register_connector)(struct drm_connector *connector);
|
||||||
void (*destroy_connector)(struct drm_dp_mst_topology_mgr *mgr,
|
void (*destroy_connector)(struct drm_dp_mst_topology_mgr *mgr,
|
||||||
struct drm_connector *connector);
|
struct drm_connector *connector);
|
||||||
void (*hotplug)(struct drm_dp_mst_topology_mgr *mgr);
|
void (*hotplug)(struct drm_dp_mst_topology_mgr *mgr);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user